1 |
60 |
zero_gravi |
:sectnums:
|
2 |
|
|
== Software Framework
|
3 |
|
|
|
4 |
72 |
zero_gravi |
To make actual use of the NEORV32 processor, the project comes with a complete software ecosystem. This
|
5 |
60 |
zero_gravi |
ecosystem is based on the RISC-V port of the GCC GNU Compiler Collection and consists of the following elementary parts:
|
6 |
|
|
|
7 |
72 |
zero_gravi |
* <<_compiler_toolchain>>
|
8 |
|
|
* <<_core_libraries>>
|
9 |
|
|
* <<_application_makefile>>
|
10 |
|
|
* <<_executable_image_format>>
|
11 |
|
|
** <<_linker_script>>
|
12 |
|
|
** <<_ram_layout>>
|
13 |
|
|
** <<_c_standard_library>>
|
14 |
|
|
** <<_start_up_code_crt0>>
|
15 |
|
|
* <<_bootloader>>
|
16 |
|
|
* <<_neorv32_runtime_environment>>
|
17 |
|
|
|
18 |
|
|
A summarizing list of the most important elements of the software framework and their according
|
19 |
|
|
files and folders is shown below:
|
20 |
|
|
|
21 |
60 |
zero_gravi |
[cols="<6,<4"]
|
22 |
|
|
[grid="none"]
|
23 |
|
|
|=======================
|
24 |
72 |
zero_gravi |
| Application start-up code | `sw/common/crt0.S`
|
25 |
|
|
| Application linker script | `sw/common/neorv32.ld`
|
26 |
|
|
| Core hardware driver libraries ("HAL") | `sw/lib/include/` & `sw/lib/source/`
|
27 |
|
|
| Central application makefile | `sw/common/common.mk`
|
28 |
|
|
| Tool for generating NEORV32 executables | `sw/image_gen/`
|
29 |
|
|
| Default bootloader | `sw/bootloader/bootloader.c`
|
30 |
|
|
| Example programs | `sw/example`
|
31 |
60 |
zero_gravi |
|=======================
|
32 |
|
|
|
33 |
72 |
zero_gravi |
.Software Documentation
|
34 |
|
|
[TIP]
|
35 |
|
|
All core libraries and example programs are highly documented using **Doxygen**.
|
36 |
|
|
See section <>.
|
37 |
|
|
The documentation is automatically built and deployed to GitHub pages and is available online
|
38 |
|
|
at https://stnolting.github.io/neorv32/sw/files.html .
|
39 |
60 |
zero_gravi |
|
40 |
72 |
zero_gravi |
|
41 |
|
|
|
42 |
60 |
zero_gravi |
// ####################################################################################################################
|
43 |
|
|
:sectnums:
|
44 |
|
|
=== Compiler Toolchain
|
45 |
|
|
|
46 |
|
|
The toolchain for this project is based on the free RISC-V GCC-port. You can find the compiler sources and
|
47 |
|
|
build instructions on the official RISC-V GNU toolchain GitHub page: https://github.com/riscv/riscv-gnutoolchain.
|
48 |
|
|
|
49 |
72 |
zero_gravi |
The NEORV32 implements a 32-bit RISC-V architecture and uses a 32-bit integer and soft-float ABI by default.
|
50 |
|
|
Make sure the toolchain / toolchain build is configured accordingly.
|
51 |
60 |
zero_gravi |
|
52 |
72 |
zero_gravi |
* MARCH = `rv32i`
|
53 |
|
|
* MABI = `ilp32`
|
54 |
|
|
|
55 |
60 |
zero_gravi |
Alternatively, you can download my prebuilt `rv32i/e` toolchains for 64-bit x86 Linux from: https://github.com/stnolting/riscv-gcc-prebuilt
|
56 |
|
|
|
57 |
72 |
zero_gravi |
The default toolchain prefix used by the project's makefiles is **`riscv32-unknown-elf`**, which can be changes
|
58 |
|
|
using makefile flags at any time.
|
59 |
60 |
zero_gravi |
|
60 |
|
|
[TIP]
|
61 |
|
|
More information regarding the toolchain (building from scratch or downloading the prebuilt ones)
|
62 |
61 |
zero_gravi |
can be found in the user guides' section https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[Software Toolchain Setup].
|
63 |
60 |
zero_gravi |
|
64 |
|
|
|
65 |
|
|
|
66 |
|
|
<<<
|
67 |
|
|
// ####################################################################################################################
|
68 |
|
|
:sectnums:
|
69 |
|
|
=== Core Libraries
|
70 |
|
|
|
71 |
72 |
zero_gravi |
The NEORV32 project provides a set of C libraries that allows an easy usage of the processor/CPU features
|
72 |
|
|
(also called "HAL" - hardware abstraction layer). All driver and runtime-related files are located in
|
73 |
|
|
`sw/lib`. These are automatically included and linked by adding the following _include statement_:
|
74 |
60 |
zero_gravi |
|
75 |
|
|
[source,c]
|
76 |
|
|
----
|
77 |
72 |
zero_gravi |
#include // add NEORV32 HAL and runtime libraries
|
78 |
60 |
zero_gravi |
----
|
79 |
|
|
|
80 |
|
|
[cols="<3,<4,<8"]
|
81 |
|
|
[options="header",grid="rows"]
|
82 |
|
|
|=======================
|
83 |
|
|
| C source file | C header file | Description
|
84 |
72 |
zero_gravi |
| - | `neorv32.h` | main NEORV32 definitions and library file
|
85 |
|
|
| `neorv32_cfs.c` | `neorv32_cfs.h` | HW driver (stubs) functions for the custom functions subsystem
|
86 |
|
|
footnote:[This driver file only represents a stub, since the real CFS drivers are defined by the actual CFS implementation.]
|
87 |
|
|
| `neorv32_cpu.c` | `neorv32_cpu.h` | HW driver functions for the NEORV32 **CPU**
|
88 |
|
|
| `neorv32_cpu_cfu.c` | `neorv32_cpu_cfu.h` | HW driver functions for the NEORV32 **CFU** (custom instructions)
|
89 |
|
|
| `neorv32_gpio.c` | `neorv32_gpio.h` | HW driver functions for the **GPIO**
|
90 |
|
|
| `neorv32_gptmr.c` | `neorv32_gptmr.h` | HW driver functions for the **GPTRM**
|
91 |
|
|
| - | `neorv32_intrinsics.h` | macros for custom intrinsics & instructions
|
92 |
|
|
| `neorv32_mtime.c` | `neorv32_mtime.h` | HW driver functions for the **MTIME**
|
93 |
|
|
| `neorv32_neoled.c` | `neorv32_neoled.h` | HW driver functions for the **NEOLED**
|
94 |
|
|
| `neorv32_pwm.c` | `neorv32_pwm.h` | HW driver functions for the **PWM**
|
95 |
|
|
| `neorv32_rte.c` | `neorv32_rte.h` | NEORV32 **runtime environment** and helper functions
|
96 |
|
|
| `neorv32_slink.c` | `neorv32_slink.h` | HW driver functions for the **SLINK**
|
97 |
|
|
| `neorv32_spi.c` | `neorv32_spi.h` | HW driver functions for the **SPI**
|
98 |
|
|
| `neorv32_trng.c` | `neorv32_trng.h` | HW driver functions for the **TRNG**
|
99 |
|
|
| `neorv32_twi.c` | `neorv32_twi.h` | HW driver functions for the **TWI**
|
100 |
|
|
| `neorv32_uart.c` | `neorv32_uart.h` | HW driver functions for the **UART0** and **UART1**
|
101 |
|
|
| `neorv32_wdt.c` | `neorv32_wdt.h` | HW driver functions for the **WDT**
|
102 |
|
|
| `neorv32_xip.c` | `neorv32_xip.h` | HW driver functions for the **XIP**
|
103 |
|
|
| `neorv32_xirq.c` | `neorv32_xirq.h` | HW driver functions for the **XIRQ**
|
104 |
|
|
| `syscalls.c` | - | newlib system calls
|
105 |
60 |
zero_gravi |
|=======================
|
106 |
|
|
|
107 |
|
|
[TIP]
|
108 |
72 |
zero_gravi |
A CMSIS-SVD-compatible **System View Description (SVD)** file including all peripherals is available in `sw/svd`.
|
109 |
|
|
`sw/lib/include`. Currently, the following library files are available:
|
110 |
60 |
zero_gravi |
|
111 |
|
|
|
112 |
|
|
|
113 |
|
|
<<<
|
114 |
|
|
// ####################################################################################################################
|
115 |
|
|
:sectnums:
|
116 |
|
|
=== Application Makefile
|
117 |
|
|
|
118 |
62 |
zero_gravi |
Application compilation is based on a single, centralized **GNU makefiles** `sw/common/common.mk`. Each project in the
|
119 |
72 |
zero_gravi |
`sw/example` folder features a makefile that just includes this central makefile. When creating a new project copy an
|
120 |
|
|
existing project folder or at least the makefile to the new project folder. It is suggested to create new projects also
|
121 |
|
|
in `sw/example` to keep the file dependencies. However, these dependencies can be manually configured via makefiles
|
122 |
|
|
variables when the new project is located somewhere else.
|
123 |
60 |
zero_gravi |
|
124 |
62 |
zero_gravi |
[NOTE]
|
125 |
72 |
zero_gravi |
Before the makefile can be used to compile applications, the RISC-V GCC toolchain needs to be installed. Furthermore,
|
126 |
|
|
the `bin` folder of the compiler needs to be added to the system's `PATH` variable. More information can be found in
|
127 |
62 |
zero_gravi |
https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[User Guide: Software Toolchain Setup].
|
128 |
60 |
zero_gravi |
|
129 |
72 |
zero_gravi |
The makefile is invoked by simply executing `make` in the console. For example:
|
130 |
60 |
zero_gravi |
|
131 |
|
|
[source,bash]
|
132 |
|
|
----
|
133 |
|
|
neorv32/sw/example/blink_led$ make
|
134 |
|
|
----
|
135 |
|
|
|
136 |
|
|
:sectnums:
|
137 |
|
|
==== Targets
|
138 |
|
|
|
139 |
62 |
zero_gravi |
Just executing `make` (or executing `make help`) will show the help menu listing all available targets.
|
140 |
60 |
zero_gravi |
|
141 |
62 |
zero_gravi |
[source,makefile]
|
142 |
|
|
----
|
143 |
|
|
$ make
|
144 |
69 |
zero_gravi |
<<< NEORV32 SW Application Makefile >>>
|
145 |
62 |
zero_gravi |
Make sure to add the bin folder of RISC-V GCC to your PATH variable.
|
146 |
69 |
zero_gravi |
|
147 |
|
|
== Targets ==
|
148 |
|
|
help - show this text
|
149 |
|
|
check - check toolchain
|
150 |
|
|
info - show makefile/toolchain configuration
|
151 |
|
|
exe - compile and generate executable for upload via bootloader
|
152 |
|
|
hex - compile and generate executable raw file
|
153 |
|
|
image - compile and generate VHDL IMEM boot image (for application) in local folder
|
154 |
|
|
install - compile, generate and install VHDL IMEM boot image (for application)
|
155 |
|
|
sim - in-console simulation using default/simple testbench and GHDL
|
156 |
|
|
all - exe + hex + install
|
157 |
|
|
elf_info - show ELF layout info
|
158 |
|
|
clean - clean up project
|
159 |
|
|
clean_all - clean up project, core libraries and image generator
|
160 |
|
|
bl_image - compile and generate VHDL BOOTROM boot image (for bootloader only!) in local folder
|
161 |
|
|
bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)
|
162 |
|
|
|
163 |
|
|
== Variables ==
|
164 |
|
|
USER_FLAGS - Custom toolchain flags [append only], default ""
|
165 |
|
|
EFFORT - Optimization level, default "-Os"
|
166 |
|
|
MARCH - Machine architecture, default "rv32i"
|
167 |
|
|
MABI - Machine binary interface, default "ilp32"
|
168 |
|
|
APP_INC - C include folder(s) [append only], default "-I ."
|
169 |
|
|
ASM_INC - ASM include folder(s) [append only], default "-I ."
|
170 |
|
|
RISCV_PREFIX - Toolchain prefix, default "riscv32-unknown-elf-"
|
171 |
|
|
NEORV32_HOME - NEORV32 home folder, default "../../.."
|
172 |
62 |
zero_gravi |
----
|
173 |
60 |
zero_gravi |
|
174 |
|
|
|
175 |
|
|
:sectnums:
|
176 |
|
|
==== Configuration
|
177 |
|
|
|
178 |
72 |
zero_gravi |
The compilation flow is configured via variables right at the beginning of the central
|
179 |
62 |
zero_gravi |
makefile (`sw/common/common.mk`):
|
180 |
60 |
zero_gravi |
|
181 |
62 |
zero_gravi |
[TIP]
|
182 |
72 |
zero_gravi |
The makefile configuration variables can be overridden or extended directly when invoking the makefile. For
|
183 |
|
|
example `$ make MARCH=rv32ic clean_all exe` overrides the default `MARCH` variable definitions.
|
184 |
|
|
Permanent modifications/definitions can be made in the project-local makefile
|
185 |
|
|
(e.g., `sw/example/blink_led/makefile`).
|
186 |
62 |
zero_gravi |
|
187 |
72 |
zero_gravi |
.Default Makefile Configuration
|
188 |
60 |
zero_gravi |
[source,makefile]
|
189 |
|
|
----
|
190 |
|
|
# *****************************************************************************
|
191 |
|
|
# USER CONFIGURATION
|
192 |
|
|
# *****************************************************************************
|
193 |
|
|
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here
|
194 |
|
|
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S)
|
195 |
|
|
# User's application include folders (don't forget the '-I' before each entry)
|
196 |
|
|
APP_INC ?= -I .
|
197 |
|
|
# User's application include folders - for assembly files only (don't forget the '-I' before each
|
198 |
|
|
entry)
|
199 |
|
|
ASM_INC ?= -I .
|
200 |
|
|
# Optimization
|
201 |
|
|
EFFORT ?= -Os
|
202 |
|
|
# Compiler toolchain
|
203 |
62 |
zero_gravi |
RISCV_PREFIX ?= riscv32-unknown-elf-
|
204 |
60 |
zero_gravi |
# CPU architecture and ABI
|
205 |
65 |
zero_gravi |
MARCH ?= rv32i
|
206 |
|
|
MABI ?= ilp32
|
207 |
60 |
zero_gravi |
# User flags for additional configuration (will be added to compiler flags)
|
208 |
|
|
USER_FLAGS ?=
|
209 |
|
|
# Relative or absolute path to the NEORV32 home folder
|
210 |
|
|
NEORV32_HOME ?= ../../..
|
211 |
|
|
# *****************************************************************************
|
212 |
|
|
----
|
213 |
|
|
|
214 |
72 |
zero_gravi |
.Variables Description
|
215 |
60 |
zero_gravi |
[cols="<3,<10"]
|
216 |
|
|
[grid="none"]
|
217 |
|
|
|=======================
|
218 |
72 |
zero_gravi |
| `APP_SRC` | The source files of the application (`*.c`, `*.cpp`, `*.S` and `*.s` files are allowed;
|
219 |
|
|
files of these types in the project folder are automatically added via wild cards). Additional files can be added separated by white spaces
|
220 |
|
|
| `APP_INC` | Include file folders; separated by white spaces; must be defined with `-I` prefix
|
221 |
|
|
| `ASM_INC` | Include file folders that are used only for the assembly source files (`*.S`/`*.s`).
|
222 |
|
|
| `EFFORT` | Optimization level, optimize for size (`-Os`) is default; legal values: `-O0`, `-O1`, `-O2`, `-O3`, `-Os`, `-Ofast`, ...
|
223 |
|
|
| `RISCV_PREFIX` | The toolchain prefix to be used; follows the triplet naming convention `[architecture]-[host_system]-[output]-...`
|
224 |
|
|
| `MARCH` | The targeted RISC-V architecture/ISA; enable compiler support of optional CPU extension by adding the according extension
|
225 |
|
|
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]
|
226 |
|
|
for more information
|
227 |
|
|
| `MABI` | Application binary interface (default: 32-bit integer ABI `ilp32`)
|
228 |
|
|
| `USER_FLAGS` | Additional flags that will be forwarded to the compiler tools
|
229 |
|
|
| `NEORV32_HOME` | Relative or absolute path to the NEORV32 project home folder; adapt this if the makefile/project is not in the project's
|
230 |
|
|
default `sw/example` folder
|
231 |
60 |
zero_gravi |
|=======================
|
232 |
|
|
|
233 |
|
|
:sectnums:
|
234 |
|
|
==== Default Compiler Flags
|
235 |
|
|
|
236 |
|
|
The following default compiler flags are used for compiling an application. These flags are defined via the
|
237 |
72 |
zero_gravi |
`CC_OPTS` variable. Custom flags can be _appended_ to it using the `USER_FLAGS` variable.
|
238 |
60 |
zero_gravi |
|
239 |
|
|
[cols="<3,<9"]
|
240 |
|
|
[grid="none"]
|
241 |
|
|
|=======================
|
242 |
72 |
zero_gravi |
| `-Wall` | Enable all compiler warnings.
|
243 |
|
|
| `-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.
|
244 |
|
|
| `-nostartfiles` | Do not use the default start code. Instead, use the NEORV32-specific start-up code (`sw/common/crt0.S`).
|
245 |
|
|
| `-Wl,--gc-sections` | Make the linker perform dead code elimination.
|
246 |
|
|
| `-lm` | Include/link with `math.h`.
|
247 |
|
|
| `-lc` | Search for the standard C library when linking.
|
248 |
|
|
| `-lgcc` | Make sure we have no unresolved references to internal GCC library subroutines.
|
249 |
|
|
| `-mno-fdiv` | Use built-in software functions for floating-point divisions and square roots (since the according instructions are not supported yet).
|
250 |
60 |
zero_gravi |
| `-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.
|
251 |
|
|
| `-falign-labels=4`
|
252 |
|
|
| `-falign-loops=4`
|
253 |
|
|
| `-falign-jumps=4`
|
254 |
|
|
|=======================
|
255 |
|
|
|
256 |
|
|
|
257 |
|
|
|
258 |
|
|
<<<
|
259 |
|
|
// ####################################################################################################################
|
260 |
|
|
:sectnums:
|
261 |
|
|
=== Executable Image Format
|
262 |
|
|
|
263 |
61 |
zero_gravi |
In order to generate a file, which can be executed by the processor, all source files have to be compiler, linked
|
264 |
|
|
and packed into a final _executable_.
|
265 |
60 |
zero_gravi |
|
266 |
61 |
zero_gravi |
:sectnums:
|
267 |
|
|
==== Linker Script
|
268 |
|
|
|
269 |
|
|
When all the application sources have been compiled, they need to be _linked_ in order to generate a unified
|
270 |
|
|
program file. For this purpose the makefile uses the NEORV32-specific linker script `sw/common/neorv32.ld` for
|
271 |
|
|
linking all object files that were generated during compilation.
|
272 |
|
|
|
273 |
|
|
The linker script defines three memory _sections_: `rom`, `ram` and `iodev`. Each section provides specific
|
274 |
|
|
access _attributes_: read access (`r`), write access (`w`) and executable (`x`).
|
275 |
|
|
|
276 |
|
|
.Linker memory sections - general
|
277 |
60 |
zero_gravi |
[cols="<2,^1,<7"]
|
278 |
|
|
[options="header",grid="rows"]
|
279 |
|
|
|=======================
|
280 |
|
|
| Memory section | Attributes | Description
|
281 |
61 |
zero_gravi |
| `ram` | `rwx` | Data memory address space (processor-internal/external DMEM)
|
282 |
|
|
| `rom` | `rx` | Instruction memory address space (processor-internal/external IMEM) _or_ internal bootloader ROM
|
283 |
|
|
| `iodev` | `rw` | Processor-internal memory-mapped IO/peripheral devices address space
|
284 |
60 |
zero_gravi |
|=======================
|
285 |
|
|
|
286 |
61 |
zero_gravi |
These sections are defined right at the beginning of the linker script:
|
287 |
60 |
zero_gravi |
|
288 |
61 |
zero_gravi |
.Linker memory sections - cut-out from linker script `neorv32.ld`
|
289 |
|
|
[source,c]
|
290 |
|
|
----
|
291 |
|
|
MEMORY
|
292 |
|
|
{
|
293 |
|
|
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024
|
294 |
|
|
rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 32K : 2048M
|
295 |
|
|
iodev (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512
|
296 |
|
|
}
|
297 |
|
|
----
|
298 |
60 |
zero_gravi |
|
299 |
61 |
zero_gravi |
Each memory section provides a _base address_ `ORIGIN` and a _size_ `LENGTH`. The base address and size of the `iodev` section is
|
300 |
72 |
zero_gravi |
fixed and should not be altered. The base addresses and sizes of the `ram` and `rom` regions correspond to the total available instruction
|
301 |
|
|
and data memory address space (see section <<_address_space_layout>>) as defined in `rtl/core/neorv32_package.vhd`.
|
302 |
60 |
zero_gravi |
|
303 |
61 |
zero_gravi |
[IMPORTANT]
|
304 |
72 |
zero_gravi |
`ORIGIN` of the `ram` section has to be always identical to the processor's `dspace_base_c` hardware configuration. +
|
305 |
|
|
+
|
306 |
61 |
zero_gravi |
`ORIGIN` of the `rom` section has to be always identical to the processor's `ispace_base_c` hardware configuration.
|
307 |
|
|
|
308 |
|
|
The sizes of `rom` section is a little bit more complicated. The default linker script configuration assumes a _maximum_ of 2GB _logical_
|
309 |
72 |
zero_gravi |
memory space, which is also the default configuration of the processor's hardware instruction memory address space. This size does not have
|
310 |
61 |
zero_gravi |
to reflect the _actual_ physical size of the instruction memory (internal IMEM and/or processor-external memory). It just provides a maximum
|
311 |
|
|
limit. When uploading new executable via the bootloader, the bootloader itself checks if sufficient _physical_ instruction memory is available.
|
312 |
|
|
If a new executable is embedded right into the internal-IMEM the synthesis tool will check, if the configured instruction memory size
|
313 |
|
|
is sufficient (e.g., via the <<_mem_int_imem_size>> generic).
|
314 |
|
|
|
315 |
|
|
[IMPORTANT]
|
316 |
|
|
The `rom` region uses a conditional assignment (via the `make_bootloader` symbol) for `ORIGIN` and `LENGTH` that is used to place
|
317 |
|
|
"normal executable" (i.e. for the IMEM) or "the bootloader image" to their according memories. +
|
318 |
|
|
+
|
319 |
|
|
The `ram` region also uses a conditional assignment (via the `make_bootloader` symbol) for `LENGTH`. When compiling the bootloader
|
320 |
|
|
(`make_bootloader` symbol is set) the generated bootloader will only use the _first_ 512 bytes of the data address space. This is
|
321 |
|
|
a fall-back to ensure the bootloader can operate independently of the actual _physical_ data memory size.
|
322 |
|
|
|
323 |
72 |
zero_gravi |
The linker maps all the regions from the compiled object files into five final sections: `.text`, `.rodata`, `.data`, `.bss` and `.heap`.
|
324 |
|
|
These regions contain everything required for the application to run:
|
325 |
61 |
zero_gravi |
|
326 |
|
|
.Linker memory regions
|
327 |
60 |
zero_gravi |
[cols="<1,<9"]
|
328 |
|
|
[options="header",grid="rows"]
|
329 |
|
|
|=======================
|
330 |
62 |
zero_gravi |
| Region | Description
|
331 |
60 |
zero_gravi |
| `.text` | Executable instructions generated from the start-up code and all application sources.
|
332 |
|
|
| `.rodata` | Constants (like strings) from the application; also the initial data for initialized variables.
|
333 |
|
|
| `.data` | This section is required for the address generation of fixed (= global) variables only.
|
334 |
|
|
| `.bss` | This section is required for the address generation of dynamic memory constructs only.
|
335 |
72 |
zero_gravi |
| `.heap` | This section is required for the address generation of dynamic memory constructs only.
|
336 |
60 |
zero_gravi |
|=======================
|
337 |
|
|
|
338 |
72 |
zero_gravi |
The `.text` and `.rodata` sections are mapped to processor's instruction memory space and the `.data`,
|
339 |
|
|
`.bss` and `heap` sections are mapped to the processor's data memory space. Finally, the `.text`, `.rodata` and `.data`
|
340 |
61 |
zero_gravi |
sections are extracted and concatenated into a single file `main.bin`.
|
341 |
60 |
zero_gravi |
|
342 |
|
|
|
343 |
61 |
zero_gravi |
:sectnums:
|
344 |
72 |
zero_gravi |
==== RAM Layout
|
345 |
|
|
|
346 |
|
|
The default NEORV32 linker script uses all of the defined RAM (linker script memory section `ram`) to create four areas.
|
347 |
|
|
Note that depending on the application some areas might not be existent at all.
|
348 |
|
|
|
349 |
|
|
.Default RAM Layout
|
350 |
|
|
image::ram_layout.png[400]
|
351 |
|
|
|
352 |
|
|
[start=1]
|
353 |
|
|
. **Constant data (`.data`)**: The constant data section is placed right at the beginning of the RAM. For example, this section
|
354 |
|
|
contains _explicitly initialized_ global variables. This section is initialized by the executable.
|
355 |
|
|
. **Dynamic data (`.bss`)**: The constant data section is followed by the dynamic data section, which contains _uninitialized_ data
|
356 |
|
|
like global variables without explicit initialization. This section is cleared by the start-up code `crt0.S`.
|
357 |
|
|
. **Heap (`.heap`)**: The heap is used for dynamic memory that is managed by functions like `malloc()` and `free()`. The heap
|
358 |
|
|
grows upwards. This section is not initialized at all.
|
359 |
|
|
. **Stack**: The stack starts at the very end of the RAM at address `ORIGIN(ram) + LENGTH(ram) - 4`. The stack grows downwards.
|
360 |
|
|
|
361 |
|
|
There is _no explicit limit_ for the maximum stack size as this is hard to check. However, a physical memory protection rule could
|
362 |
|
|
be used to configure a maximum size by adding a "protection area" between stack and heap (a PMP region without any access rights).
|
363 |
|
|
|
364 |
|
|
The maximum size of the heap is defined by the linker script's `__heap_size` symbol. This symbol can be overridden at any time.
|
365 |
|
|
By default, the maximum heap size is 1/4 of the total RAM size.
|
366 |
|
|
|
367 |
|
|
.Heap-Stack Collisions
|
368 |
|
|
[WARNING]
|
369 |
|
|
Take care when using dynamic memory to avoid collision of the heap and stack memory areas. There is no compile-time protection
|
370 |
|
|
mechanism available as the actual heap and stack size are defined by _runtime_ data. Also beware of fragmentation when
|
371 |
|
|
using dynamic memory allocation.
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
:sectnums:
|
375 |
|
|
==== C Standard Library
|
376 |
|
|
|
377 |
|
|
.Constructors and Deconstructors
|
378 |
|
|
[IMPORTANT]
|
379 |
|
|
The NEORV32 processor is an embedded system intended for running bare-metal or RTOS applications. To simplify this setup
|
380 |
|
|
explicit constructors and deconstructors are not supported by default. However, a minimal "deconstructor-alike" support is
|
381 |
|
|
provided by the <<_after_main_handler>>.
|
382 |
|
|
|
383 |
|
|
The NEORV32 is a processor for _embedded_ applications. Hence, it is not capable of running desktop OSs like Linux
|
384 |
|
|
(at least not without emulation). Hence, the software framework relies on a "bare-metal" setup that uses **newlib**
|
385 |
|
|
as default C standard library.
|
386 |
|
|
|
387 |
|
|
.RTOS Support
|
388 |
|
|
[NOTE]
|
389 |
|
|
The NEORV32 CPU and processor **do support** embedded RTOS like FreeRTOS and Zephyr. See the User guide section
|
390 |
|
|
https://stnolting.github.io/neorv32/ug/#_zephyr_rtos_support[Zephyr RTOS Support] and
|
391 |
|
|
https://stnolting.github.io/neorv32/ug/#_freertos_support[FreeRTOS Support]
|
392 |
|
|
for more information.
|
393 |
|
|
|
394 |
|
|
Newlib provides stubs for common "system calls" (like file handling and standard input/output) that are used by other
|
395 |
|
|
C libraries like `stdio`. These stubs are available in `sw/source/syscalls.c` and were adapted for the NEORV32 processor.
|
396 |
|
|
|
397 |
|
|
.Standard Console(s)
|
398 |
|
|
[NOTE]
|
399 |
|
|
<<_primary_universal_asynchronous_receiver_and_transmitter_uart0, UART0>>
|
400 |
|
|
is used to implement all the standard input, output and error consoles (`STDIN`, `STDOUT` and `STDERR`).
|
401 |
|
|
|
402 |
|
|
.Newlib Test/Demo Program
|
403 |
|
|
[TIP]
|
404 |
|
|
A simple test and demo program, which uses some of newlib's core functions (like `malloc`/`free` and `read`/`write`)
|
405 |
|
|
is available in `sw/example_newlib_demo`
|
406 |
|
|
|
407 |
|
|
|
408 |
|
|
:sectnums:
|
409 |
61 |
zero_gravi |
==== Executable Image Generator
|
410 |
60 |
zero_gravi |
|
411 |
61 |
zero_gravi |
The `main.bin` file is packed by the NEORV32 image generator (`sw/image_gen`) to generate the final executable file.
|
412 |
|
|
|
413 |
|
|
[NOTE]
|
414 |
|
|
The sources of the image generator are automatically compiled when invoking the makefile.
|
415 |
|
|
|
416 |
|
|
The image generator can generate three types of executables, selected by a flag when calling the generator:
|
417 |
|
|
|
418 |
60 |
zero_gravi |
[cols="<1,<9"]
|
419 |
|
|
[grid="none"]
|
420 |
|
|
|=======================
|
421 |
|
|
| `-app_bin` | Generates an executable binary file `neorv32_exe.bin` (for UART uploading via the bootloader).
|
422 |
62 |
zero_gravi |
| `-app_hex` | Generates a plain ASCII hex-char file `neorv32_exe.hex` that can be used to initialize custom (instruction-) memories (in synthesis/simulation).
|
423 |
60 |
zero_gravi |
| `-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.
|
424 |
|
|
| `-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.
|
425 |
|
|
|=======================
|
426 |
|
|
|
427 |
61 |
zero_gravi |
All these options are managed by the makefile. The _normal application_ compilation flow will generate the `neorv32_exe.bin`
|
428 |
|
|
executable to be upload via UART to the NEORV32 bootloader.
|
429 |
60 |
zero_gravi |
|
430 |
61 |
zero_gravi |
The image generator add a small header to the `neorv32_exe.bin` executable, which consists of three 32-bit words located right at the
|
431 |
|
|
beginning of the file. The first word of the executable is the signature word and is always `0x4788cafe`. Based on this word the bootloader
|
432 |
|
|
can identify a valid image file. The next word represents the size in bytes of the actual program
|
433 |
60 |
zero_gravi |
image in bytes. A simple "complement" checksum of the actual program image is given by the third word. This
|
434 |
|
|
provides a simple protection against data transmission or storage errors.
|
435 |
|
|
|
436 |
|
|
|
437 |
61 |
zero_gravi |
:sectnums:
|
438 |
|
|
==== Start-Up Code (crt0)
|
439 |
60 |
zero_gravi |
|
440 |
61 |
zero_gravi |
The CPU and also the processor require a minimal start-up and initialization code to bring the CPU (and the SoC)
|
441 |
|
|
into a stable and initialized state and to initialize the C runtime environment before the actual application can be executed.
|
442 |
|
|
This start-up code is located in `sw/common/crt0.S` and is automatically linked _every_ application program
|
443 |
|
|
and placed right before the actual application code so it gets executed right after reset.
|
444 |
60 |
zero_gravi |
|
445 |
61 |
zero_gravi |
The `crt0.S` start-up performs the following operations:
|
446 |
60 |
zero_gravi |
|
447 |
61 |
zero_gravi |
[start=1]
|
448 |
|
|
. Initialize all integer registers `x1 - x31` (or jsut `x1 - x15` when using the `E` CPU extension) to a defined value.
|
449 |
|
|
. Initialize the global pointer `gp` and the stack pointer `sp` according to the `.data` segment layout provided by the linker script.
|
450 |
|
|
. 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.
|
451 |
|
|
. 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.
|
452 |
|
|
. Clear the `.bss` section defined by the linker script.
|
453 |
|
|
. Copy read-only data from the `.text` section to the `.data` section to set initialized variables.
|
454 |
|
|
. Call the application's `main` function (with _no_ arguments: `argc` = `argv` = 0).
|
455 |
|
|
. If the `main` function returns `crt0` can call an "after-main handler" (see below)
|
456 |
|
|
. 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).
|
457 |
60 |
zero_gravi |
|
458 |
61 |
zero_gravi |
:sectnums:
|
459 |
|
|
===== After-Main Handler
|
460 |
|
|
|
461 |
|
|
If the application's `main()` function actually returns, an _after main handler_ can be executed. This handler can be a normal function
|
462 |
|
|
since the C runtime is still available when executed. If this handler uses any kind of peripheral/IO modules make sure these are
|
463 |
|
|
already initialized within the application or you have to initialize them _inside_ the handler.
|
464 |
|
|
|
465 |
|
|
.After-main handler - function prototype
|
466 |
|
|
[source,c]
|
467 |
|
|
----
|
468 |
|
|
int __neorv32_crt0_after_main(int32_t return_code);
|
469 |
|
|
----
|
470 |
|
|
|
471 |
|
|
The function has exactly one argument (`return_code`) that provides the _return value_ of the application's main function.
|
472 |
|
|
For instance, this variable contains _-1_ if the main function returned with `return -1;`. The return value of the
|
473 |
|
|
`__neorv32_crt0_after_main` function is irrelevant as there is no further "software instance" executed afterwards that can check this.
|
474 |
|
|
However, the on-chip debugger could still evaluate the return value of the after-main handler.
|
475 |
|
|
|
476 |
72 |
zero_gravi |
A simple UARt output can be used to inform the user when the application's main function returns
|
477 |
61 |
zero_gravi |
(this example assumes that UART0 has been already properly configured in the actual application):
|
478 |
|
|
|
479 |
72 |
zero_gravi |
.After-main handler - simple example
|
480 |
61 |
zero_gravi |
[source,c]
|
481 |
|
|
----
|
482 |
|
|
int __neorv32_crt0_after_main(int32_t return_code) {
|
483 |
|
|
|
484 |
72 |
zero_gravi |
neorv32_uart0_printf("\n main function returned with exit code %i. \n", return_code); <1>
|
485 |
61 |
zero_gravi |
return 0;
|
486 |
|
|
}
|
487 |
|
|
----
|
488 |
72 |
zero_gravi |
<1> Use `` here to make clear this is a message comes from the runtime environment.
|
489 |
61 |
zero_gravi |
|
490 |
|
|
|
491 |
60 |
zero_gravi |
<<<
|
492 |
|
|
// ####################################################################################################################
|
493 |
|
|
|
494 |
72 |
zero_gravi |
include::software_bootloader.adoc[]
|
495 |
60 |
zero_gravi |
|
496 |
|
|
|
497 |
|
|
|
498 |
|
|
<<<
|
499 |
|
|
// ####################################################################################################################
|
500 |
|
|
|
501 |
72 |
zero_gravi |
include::software_rte.adoc[]
|