Skip to content

Commit 9dc3472

Browse files
authored
[RTE] minor updates (#742)
2 parents 1b4e9e1 + bc43b6c commit 9dc3472

File tree

3 files changed

+129
-19
lines changed

3 files changed

+129
-19
lines changed

docs/datasheet/software_rte.adoc

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ by resolving the trap cause.
3636

3737
==== Using the RTE
3838

39+
[IMPORTANT]
40+
All provided RTE functions can be called only from machine-mode code.
41+
3942
The NEORV32 is part of the default NEORV32 software framework. However, it has to explicitly enabled by calling
4043
the RTE's setup function:
4144

@@ -48,6 +51,10 @@ void neorv32_rte_setup(void);
4851
[NOTE]
4952
The RTE should be enabled right at the beginning of the application's `main` function.
5053

54+
[IMPORTANT]
55+
It is recommended to not use the <<_mscratch>> CSR when using the RTE as this register is used to provide services
56+
for <<_application_context_handling>> (i.e. modifying the registers of application code that caused a trap).
57+
5158
As mentioned above, all traps will just trigger execution of the RTE's <<_default_rte_trap_handlers>> at first.
5259
To use application-specific handlers, which actually "handle" a trap, the default handlers can be overridden
5360
by installing user-defined ones:
@@ -142,6 +149,9 @@ RISC-V machine timer (MTIME) interrupt:
142149
neorv32_rte_handler_uninstall(RTE_TRAP_MTI);
143150
----
144151

152+
[TIP]
153+
The current RTE configuration can be printed via UART0 via the `neorv32_rte_info` function.
154+
145155

146156
==== Default RTE Trap Handlers
147157

sw/lib/include/neorv32_rte.h

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ int neorv32_rte_handler_install(int id, void (*handler)(void));
9393
int neorv32_rte_handler_uninstall(int id);
9494
uint32_t neorv32_rte_context_get(int x);
9595
void neorv32_rte_context_put(int x, uint32_t data);
96+
void neorv32_rte_print_info(void);
9697

9798
void neorv32_rte_print_hw_config(void);
9899
void neorv32_rte_print_hw_version(void);

sw/lib/source/neorv32_rte.c

+118-19
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949

5050
/**********************************************************************//**
51-
* NEORV32 runtime environment (RTE).
51+
* NEORV32 runtime environment (RTE):
5252
* The >private< trap vector look-up table of the NEORV32 RTE.
5353
**************************************************************************/
5454
static uint32_t __neorv32_rte_vector_lut[NEORV32_RTE_NUM_TRAPS] __attribute__((unused)); // trap handler vector table
@@ -61,15 +61,20 @@ static void __neorv32_rte_print_hex_word(uint32_t num);
6161

6262

6363
/**********************************************************************//**
64-
* NEORV32 runtime environment (RTE).
64+
* NEORV32 runtime environment (RTE):
6565
* Setup RTE.
6666
*
6767
* @note This function installs a debug handler for ALL trap sources, which
6868
* gives detailed information about the trap. Actual handlers can be installed afterwards
6969
* via neorv32_rte_handler_install(uint8_t id, void (*handler)(void)).
70+
*
71+
* @warning This function can be called from machine-mode only.
7072
**************************************************************************/
7173
void neorv32_rte_setup(void) {
7274

75+
// raise an exception if we're not in machine-mode
76+
asm volatile ("csrr x0, mhartid");
77+
7378
// clear mstatus, set previous privilege level to machine-mode
7479
neorv32_cpu_csr_write(CSR_MSTATUS, (1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L));
7580

@@ -91,15 +96,20 @@ void neorv32_rte_setup(void) {
9196

9297

9398
/**********************************************************************//**
94-
* NEORV32 runtime environment (RTE).
99+
* NEORV32 runtime environment (RTE):
95100
* Install trap handler function (second-level trap handler).
96101
*
97102
* @param[in] id Identifier (type) of the targeted trap. See #NEORV32_RTE_TRAP_enum.
98103
* @param[in] handler The actual handler function for the specified trap (function MUST be of type "void function(void);").
99104
* @return 0 if success, -1 if error (invalid id or targeted trap not supported).
105+
*
106+
* @warning This function can be called from machine-mode only.
100107
**************************************************************************/
101108
int neorv32_rte_handler_install(int id, void (*handler)(void)) {
102109

110+
// raise an exception if we're not in machine-mode
111+
asm volatile ("csrr x0, mhartid");
112+
103113
// id valid?
104114
if ((id >= (int)RTE_TRAP_I_MISALIGNED) && (id <= (int)RTE_TRAP_FIRQ_15)) {
105115
__neorv32_rte_vector_lut[id] = (uint32_t)handler; // install handler
@@ -110,15 +120,20 @@ int neorv32_rte_handler_install(int id, void (*handler)(void)) {
110120

111121

112122
/**********************************************************************//**
113-
* NEORV32 runtime environment (RTE).
123+
* NEORV32 runtime environment (RTE):
114124
* Uninstall trap handler function from NEORV32 runtime environment, which was
115125
* previously installed via neorv32_rte_handler_install(uint8_t id, void (*handler)(void)).
116126
*
117127
* @param[in] id Identifier (type) of the targeted trap. See #NEORV32_RTE_TRAP_enum.
118128
* @return 0 if success, -1 if error (invalid id or targeted trap not supported).
129+
*
130+
* @warning This function can be called from machine-mode only.
119131
**************************************************************************/
120132
int neorv32_rte_handler_uninstall(int id) {
121133

134+
// raise an exception if we're not in machine-mode
135+
asm volatile ("csrr x0, mhartid");
136+
122137
// id valid?
123138
if ((id >= (int)RTE_TRAP_I_MISALIGNED) && (id <= (int)RTE_TRAP_FIRQ_15)) {
124139
__neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_handler); // use dummy handler in case the trap is accidentally triggered
@@ -129,15 +144,20 @@ int neorv32_rte_handler_uninstall(int id) {
129144

130145

131146
/**********************************************************************//**
132-
* NEORV32 runtime environment (RTE).
147+
* NEORV32 runtime environment (RTE):
133148
* This is the core of the NEORV32 RTE (first-level trap handler, executed in machine mode).
134149
**************************************************************************/
135150
static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
136151

137152
// save context
138-
asm volatile (
153+
asm volatile (
139154
"csrw mscratch, sp \n" // backup original stack pointer
155+
156+
#ifndef __riscv_32e
140157
"addi sp, sp, -32*4 \n"
158+
#else
159+
"addi sp, sp, -16*4 \n"
160+
#endif
141161

142162
"sw x0, 0*4(sp) \n"
143163
"sw x1, 1*4(sp) \n"
@@ -241,6 +261,7 @@ static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
241261
asm volatile (
242262
// "lw x0, 0*4(sp) \n"
243263
"lw x1, 1*4(sp) \n"
264+
// restore 2x at the very end
244265
"lw x3, 3*4(sp) \n"
245266
"lw x4, 4*4(sp) \n"
246267
"lw x5, 5*4(sp) \n"
@@ -279,9 +300,11 @@ static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
279300

280301

281302
/**********************************************************************//**
282-
* NEORV32 runtime environment:
303+
* NEORV32 runtime environment (RTE):
283304
* Read register from application context.
284305
*
306+
* @warning This function can be called from machine-mode only.
307+
*
285308
* @param[in] x Register number (0..31, corresponds to register x0..x31).
286309
* @return Content of register x.
287310
**************************************************************************/
@@ -298,9 +321,11 @@ uint32_t neorv32_rte_context_get(int x) {
298321

299322

300323
/**********************************************************************//**
301-
* NEORV32 runtime environment:
324+
* NEORV32 runtime environment (RTE):
302325
* Write register in application context.
303326
*
327+
* @warning This function can be called from machine-mode only.
328+
*
304329
* @param[in] x Register number (0..31, corresponds to register x0..x31).
305330
* @param[in] data Data to be written to register x.
306331
**************************************************************************/
@@ -317,8 +342,8 @@ void neorv32_rte_context_put(int x, uint32_t data) {
317342

318343

319344
/**********************************************************************//**
320-
* NEORV32 runtime environment (RTE).
321-
* Debug trap handler, printing various information via UART.
345+
* NEORV32 runtime environment (RTE):
346+
* Debug trap handler, printing various information via UART0.
322347
**************************************************************************/
323348
static void __neorv32_rte_debug_handler(void) {
324349

@@ -403,17 +428,87 @@ static void __neorv32_rte_debug_handler(void) {
403428
}
404429

405430

431+
/**********************************************************************//**
432+
* NEORV32 runtime environment (RTE):
433+
* Print current RTE configuration via UART0.
434+
*
435+
* @warning This function can be called from machine-mode only.
436+
**************************************************************************/
437+
void neorv32_rte_print_info(void) {
438+
439+
// raise an exception if we're not in machine-mode
440+
asm volatile ("csrr x0, mhartid");
441+
442+
const char trap_name[NEORV32_RTE_NUM_TRAPS][13] = {
443+
"I_MISALIGNED",
444+
"I_ACCESS ",
445+
"I_ILLEGAL ",
446+
"BREAKPOINT ",
447+
"L_MISALIGNED",
448+
"L_ACCESS ",
449+
"S_MISALIGNED",
450+
"S_ACCESS ",
451+
"UENV_CALL ",
452+
"MENV_CALL ",
453+
"MSI ",
454+
"MTI ",
455+
"MEI ",
456+
"FIRQ_0 ",
457+
"FIRQ_1 ",
458+
"FIRQ_2 ",
459+
"FIRQ_3 ",
460+
"FIRQ_4 ",
461+
"FIRQ_5 ",
462+
"FIRQ_6 ",
463+
"FIRQ_7 ",
464+
"FIRQ_8 ",
465+
"FIRQ_9 ",
466+
"FIRQ_10 ",
467+
"FIRQ_11 ",
468+
"FIRQ_12 ",
469+
"FIRQ_13 ",
470+
"FIRQ_14 ",
471+
"FIRQ_15 "
472+
};
473+
474+
neorv32_uart0_puts("\n\n<< NEORV32 Runtime Environment (RTE) Configuration >>\n\n");
475+
476+
// header
477+
neorv32_uart0_puts("---------------------------------\n");
478+
neorv32_uart0_puts("Trap Name [ID] Handler\n");
479+
neorv32_uart0_puts("---------------------------------\n");
480+
481+
uint32_t i;
482+
for (i=0; i<NEORV32_RTE_NUM_TRAPS; i++) {
483+
neorv32_uart0_puts("RTE_TRAP_");
484+
neorv32_uart0_puts(trap_name[i]);
485+
neorv32_uart0_puts(" ");
486+
__neorv32_rte_print_hex_word(__neorv32_rte_vector_lut[i]);
487+
neorv32_uart0_puts("\n");
488+
}
489+
490+
// footer
491+
neorv32_uart0_puts("---------------------------------\n");
492+
neorv32_uart0_puts("\n");
493+
}
494+
495+
406496
// #################################################################################################
407497
// RTE Hardware Analysis Helpers
408498
// #################################################################################################
409499

410500

411501
/**********************************************************************//**
412-
* NEORV32 runtime environment:
502+
* NEORV32 runtime environment (RTE):
413503
* Print hardware configuration information via UART0.
504+
*
505+
* @warning This function can be called from machine-mode only.
414506
**************************************************************************/
415507
void neorv32_rte_print_hw_config(void) {
416508

509+
// raise an exception if we're not in machine-mode
510+
asm volatile ("csrr x0, mhartid");
511+
417512
if (neorv32_uart0_available() == 0) {
418513
return; // cannot output anything if UART0 is not implemented
419514
}
@@ -618,7 +713,7 @@ void neorv32_rte_print_hw_config(void) {
618713

619714

620715
/**********************************************************************//**
621-
* NEORV32 runtime environment:
716+
* NEORV32 runtime environment (RTE):
622717
* Private function to print true or false via UART0.
623718
*
624719
* @param[in] state Print 'true' when !=0, print 'false' when 0
@@ -635,7 +730,7 @@ static void __neorv32_rte_print_true_false(int state) {
635730

636731

637732
/**********************************************************************//**
638-
* NEORV32 runtime environment:
733+
* NEORV32 runtime environment (RTE):
639734
* Private function to print 32-bit number as 8-digit hexadecimal value (with "0x" suffix).
640735
*
641736
* @param[in] num Number to print as hexadecimal via UART0.
@@ -660,8 +755,10 @@ void __neorv32_rte_print_hex_word(uint32_t num) {
660755

661756

662757
/**********************************************************************//**
663-
* NEORV32 runtime environment:
758+
* NEORV32 runtime environment (RTE):
664759
* Print the processor version in human-readable format via UART0.
760+
*
761+
* @warning This function can be called from machine-mode only.
665762
**************************************************************************/
666763
void neorv32_rte_print_hw_version(void) {
667764

@@ -695,7 +792,7 @@ void neorv32_rte_print_hw_version(void) {
695792

696793

697794
/**********************************************************************//**
698-
* NEORV32 runtime environment:
795+
* NEORV32 runtime environment (RTE):
699796
* Print project credits via UART0.
700797
**************************************************************************/
701798
void neorv32_rte_print_credits(void) {
@@ -710,7 +807,7 @@ void neorv32_rte_print_credits(void) {
710807

711808

712809
/**********************************************************************//**
713-
* NEORV32 runtime environment:
810+
* NEORV32 runtime environment (RTE):
714811
* Print project logo via UART0.
715812
**************************************************************************/
716813
void neorv32_rte_print_logo(void) {
@@ -754,7 +851,7 @@ void neorv32_rte_print_logo(void) {
754851

755852

756853
/**********************************************************************//**
757-
* NEORV32 runtime environment:
854+
* NEORV32 runtime environment (RTE):
758855
* Print project license via UART0.
759856
**************************************************************************/
760857
void neorv32_rte_print_license(void) {
@@ -799,7 +896,7 @@ void neorv32_rte_print_license(void) {
799896

800897

801898
/**********************************************************************//**
802-
* NEORV32 runtime environment:
899+
* NEORV32 runtime environment (RTE):
803900
* Get MISA CSR value according to *compiler/toolchain configuration*.
804901
*
805902
* @return MISA content according to compiler configuration.
@@ -851,9 +948,11 @@ uint32_t neorv32_rte_get_compiler_isa(void) {
851948

852949

853950
/**********************************************************************//**
854-
* NEORV32 runtime environment:
951+
* NEORV32 runtime environment (RTE):
855952
* Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
856953
*
954+
* @warning This function can be called from machine-mode only.
955+
*
857956
* @param[in] silent Show error message (via UART0) if isa_sw > isa_hw when = 0.
858957
* @return MISA content according to compiler configuration.
859958
**************************************************************************/

0 commit comments

Comments
 (0)