URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
[/] [neorv32/] [trunk/] [docs/] [datasheet/] [software_rte.adoc] - Rev 72
Compare with Previous | Blame | View Log
:sectnums:=== NEORV32 Runtime EnvironmentThe NEORV32 software framework provides a minimal runtime environment (**RTE**) that takes care of a stableand _safe_ execution environment by handling _all_ traps (= exceptions & interrupts). The RTE simplifies trap handlingby wrapping the CPU's _privileged architecture_ (i.e. trap-related CSRs) into a unified software API.The NEORV32 RTE is a software library (`sw/lib/source/neorv32_rte.c`) that is part of the default processor library set.It provides public functions via `sw/lib/include/neorv32_rte.h` for application interaction.Once initialized, the RTE provides <<_default_rte_trap_handlers>> that catch all possible exceptions. Thesedefault handlers just output a message via UART to inform the user when a certain trap has been triggered. Thedefault handlers can be overridden by the application code to install application-specific handler functions for each trap.[IMPORTANT]Using the RTE is **optional but highly recommended**. The RTE provides a simple and comfortable way of delegatingtraps to application-specific handlers while making sure that all traps (even though they are not explicitly usedby the application) are handled correctly. Performance-optimized applications or embedded operating systems shouldnot use the RTE for delegating traps.[NOTE]For the **C standard runtime library** see section <<c_standard_library>>.==== RTE OperationThe RTE handles the trap-related CSRs of the CPU's privileged architecture (<<_machine_trap_handling_csrs>>).It initializes the <<_mtvec>> CSR, which provides the base entry point for all traphandlers. The address stored to this register reflects the **first-level exception handler**, which is provided by theNEORV32 RTE. Whenever an exception or interrupt is triggered this first-level handler is executed.The first-level handler performs a complete context save, analyzes the source of the exception/interrupt andcalls the according **second-level exception handler**, which takes care of the actual exception/interrupthandling. For this, the RTE manages a private look-up table to store the addresses of the according traphandlers.After the initial RTE setup, each entry in the RTE's trap handler's look-up table is initialized with a<<_default_rte_trap_handlers>>. These default handler do not execute any trap-related operations - theyjust output a message via the *primary UART (UART0)* to inform the user that a trap has occurred, that is nothandled by the actual application. After sending this message, the RTE tries to continue executing the user program.==== Using the RTEThe NEORV32 is enabled by calling the RTE's setup function:.Function Prototype: RTE Setup[source,c]----void neorv32_rte_setup(void);----[NOTE]The RTE should be enabled right at the beginning of the application's `main` function.As mentioned above, _all_ traps will only trigger execution of the RTE's <<_default_rte_trap_handlers>>.To use application-specific handlers, which actually _handle_ a trap, the default handlers can be overriddenby installing user-defined ones:.Function Prototype: Installing an Application-Specific Trap Handler[source,c]----int neorv32_rte_exception_install(uint8_t id, void (*handler)(void));----The first argument `id` defines the "trap ID" (for example a certain interrupt request) that shall be handledby the user-defined handler. The second argument `*handler` is the actual function that implements the traphandler. The function return zero on success and a non-zero value if an error occurred (invalid `id`). In thiscase no modifications to the RTE's trap look-up-table will be made.The custom handler functions need to have a specific format without any arguments an with no return value:.Function Prototype: Custom Trap Handler[source,c]----void custom_trap_handler_xyz(void) {// handle exception/interrupt...}----.Custom Trap Handler Attributes[WARNING]Do NOT use the `((interrupt))` attribute for the application exception handler functions! Thiswill place a `mret` instruction to the end of it making it impossible to return to the first-levelexception handler of the RTE core, which will cause stack corruption.The trap identifier `id` specifies the according trap cause. These can be an _asynchronous trap_ likean interrupt from one of the processor modules or a _synchronous trap_ triggered by software-caused eventslike an illegal instruction or an environment call instruction. The `sw/lib/include/neorv32_rte.h` library filesprovides aliases for trap events supported by the CPU (see <<_neorv32_trap_listing>>) that can be used wheninstalling custom trap handler functions:.RTE Trap ID List[cols="<5,<12"][options="header",grid="rows"]|=======================| ID alias [C] | Description / trap causing event| `RTE_TRAP_I_MISALIGNED` | instruction address misaligned| `RTE_TRAP_I_ACCESS` | instruction (bus) access fault| `RTE_TRAP_I_ILLEGAL` | illegal instruction| `RTE_TRAP_BREAKPOINT` | breakpoint (`ebreak` instruction)| `RTE_TRAP_L_MISALIGNED` | load address misaligned| `RTE_TRAP_L_ACCESS` | load (bus) access fault| `RTE_TRAP_S_MISALIGNED` | store address misaligned| `RTE_TRAP_S_ACCESS` | store (bus) access fault| `RTE_TRAP_MENV_CALL` | environment call from machine mode (`ecall` instruction)| `RTE_TRAP_UENV_CALL` | environment call from user mode (`ecall` instruction)| `RTE_TRAP_MTI` | machine timer interrupt| `RTE_TRAP_MEI` | machine external interrupt| `RTE_TRAP_MSI` | machine software interrupt| `RTE_TRAP_FIRQ_0` | fast interrupt channel 0| `RTE_TRAP_FIRQ_1` | fast interrupt channel 1| `RTE_TRAP_FIRQ_2` | fast interrupt channel 2| `RTE_TRAP_FIRQ_3` | fast interrupt channel 3| `RTE_TRAP_FIRQ_4` | fast interrupt channel 4| `RTE_TRAP_FIRQ_5` | fast interrupt channel 5| `RTE_TRAP_FIRQ_6` | fast interrupt channel 6| `RTE_TRAP_FIRQ_7` | fast interrupt channel 7| `RTE_TRAP_FIRQ_8` | fast interrupt channel 8| `RTE_TRAP_FIRQ_9` | fast interrupt channel 9| `RTE_TRAP_FIRQ_10` | fast interrupt channel 10| `RTE_TRAP_FIRQ_11` | fast interrupt channel 11| `RTE_TRAP_FIRQ_12` | fast interrupt channel 12| `RTE_TRAP_FIRQ_13` | fast interrupt channel 13| `RTE_TRAP_FIRQ_14` | fast interrupt channel 14| `RTE_TRAP_FIRQ_15` | fast interrupt channel 15|=======================The following example shows how to install a custom handler (`custom_mtime_irq_handler`) for handlingthe RISC-V machine timer (MTIME) interrupt:.Example: Installing the MTIME IRQ Handler[source,c]----neorv32_rte_exception_install(RTE_TRAP_MTI, custom_mtime_irq_handler);----User-defined trap handlers can also be un-installed. This will remove the users trap handler from the RTE coreand will re-install the <<_default_rte_trap_handlers>> for the specific trap..Function Prototype: Installing an Application-Specific Trap Handler[source,c]----int neorv32_rte_exception_uninstall(uint8_t id);----The argument `id` defines the identifier of the according trap that shall be un-installed. The function return zeroon success and a non-zero value if an error occurred (invalid `id`). In this case no modifications to the RTE's traplook-up-table will be made.The following example shows how to un-install the custom handler `custom_mtime_irq_handler` from theRISC-V machine timer (MTIME) interrupt:.Example: Removing the Custom MTIME IRQ Handler[source,c]----neorv32_rte_exception_uninstall(RTE_TRAP_MTI);----==== Default RTE Trap HandlersThe default RTE trap handlers are executed when a certain trap is triggered that is not handled by a user-definedapplication-specific trap handler. These default handler will just output a message giving additional debug informationvia UART0 to inform the user and will try to resume normal execution of the application..Continuing Execution[IMPORTAN]In most cases the RTE can successfully continue operation when it catches an interrupt request, which is not handledby the actual application program. However, if the RTE catches an un_handled exception like a bus access faultcontinuing execution will most likely fail and the CPU will crash..RTE Default Trap Handler Output Example (Illegal Instruction)[source]----<RTE> Illegal instruction @ PC=0x000002d6, MTVAL=0x00001537 </RTE>----In this example the "Illegal instruction" _message_ describes the cause of the trap, which is an illegal instructionexception here. `PC` shows the current program counter value when the trap occurred and `MTVAL` shows additionaldebug information from the <<_mtval>> CSR. In this case it shows the encoding of the illegal instruction.The specific _message_ corresponds to the trap code from the <<_mcause>> CSR (see <<_neorv32_trap_listing>>).A full list of all messages and the according `mcause` trap codes are shown below..RTE Default Trap Handler Messages and According `mcause` Values[cols="<5,^5"][options="header",grid="rows"]|=======================| Trap identifier | According `mcause` CSR value| "Instruction address misaligned" | `0x00000000`| "Instruction access fault" | `0x00000001`| "Illegal instruction" | `0x00000002`| "Breakpoint" | `0x00000003`| "Load address misaligned" | `0x00000004`| "Load access fault" | `0x00000005`| "Store address misaligned" | `0x00000006`| "Store access fault" | `0x00000007`| "Environment call from U-mode" | `0x00000008`| "Environment call from M-mode" | `0x0000000b`| "Machine software interrupt" | `0x80000003`| "Machine timer interrupt" | `0x80000007`| "Machine external interrupt" | `0x8000000b`| "Fast interrupt 0" | `0x80000010`| "Fast interrupt 1" | `0x80000011`| "Fast interrupt 2" | `0x80000012`| "Fast interrupt 3" | `0x80000013`| "Fast interrupt 4" | `0x80000014`| "Fast interrupt 5" | `0x80000015`| "Fast interrupt 6" | `0x80000016`| "Fast interrupt 7" | `0x80000017`| "Fast interrupt 8" | `0x80000018`| "Fast interrupt 9" | `0x80000019`| "Fast interrupt a" | `0x8000001a`| "Fast interrupt b" | `0x8000001b`| "Fast interrupt c" | `0x8000001c`| "Fast interrupt d" | `0x8000001d`| "Fast interrupt e" | `0x8000001e`| "Fast interrupt f" | `0x8000001f`| "Unknown trap cause" | _not defined_|============================ Bus Access FaultsFor bus access faults the RTE default trap handlers also output the error code from the<<_internal_bus_monitor_buskeeper>> to show the cause of the bus fault. One example is shown below..RTE Default Trap Handler Output Example (Load Access Bus Fault)[source]----<RTE> Load access fault [TIMEOUT_ERR] @ PC=0x00000150, MTVAL=0xFFFFFF70 </RTE>----The additional message encapsulated in `[ ]` shows the actual cause of the bus access fault.Three different messages are possible here:* `[TIMEOUT_ERR]`: The accessed memory-mapped module did not respond within the valid access time window.In Most cases this is caused by accessing a module that has not been implemented or when accessing"address space holes" (unused/unmapped addresses).* `[DEVICE_ERR]`: The accesses memory-mapped module asserted it's error signal to indicate an invalid access.For example this can be caused by trying to write to read-only registers or by writing data quantities (like a byte)to devices that do not support sub-word write accesses.* `[PMP_ERR]`: This indicates an access right violation caused by the <<_pmp_physical_memory_protection>>.
