48
48
49
49
50
50
/**********************************************************************/ /**
51
- * NEORV32 runtime environment (RTE).
51
+ * NEORV32 runtime environment (RTE):
52
52
* The >private< trap vector look-up table of the NEORV32 RTE.
53
53
**************************************************************************/
54
54
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);
61
61
62
62
63
63
/**********************************************************************/ /**
64
- * NEORV32 runtime environment (RTE).
64
+ * NEORV32 runtime environment (RTE):
65
65
* Setup RTE.
66
66
*
67
67
* @note This function installs a debug handler for ALL trap sources, which
68
68
* gives detailed information about the trap. Actual handlers can be installed afterwards
69
69
* via neorv32_rte_handler_install(uint8_t id, void (*handler)(void)).
70
+ *
71
+ * @warning This function can be called from machine-mode only.
70
72
**************************************************************************/
71
73
void neorv32_rte_setup (void ) {
72
74
75
+ // raise an exception if we're not in machine-mode
76
+ asm volatile ("csrr x0, mhartid" );
77
+
73
78
// clear mstatus, set previous privilege level to machine-mode
74
79
neorv32_cpu_csr_write (CSR_MSTATUS , (1 <<CSR_MSTATUS_MPP_H ) | (1 <<CSR_MSTATUS_MPP_L ));
75
80
@@ -91,15 +96,20 @@ void neorv32_rte_setup(void) {
91
96
92
97
93
98
/**********************************************************************/ /**
94
- * NEORV32 runtime environment (RTE).
99
+ * NEORV32 runtime environment (RTE):
95
100
* Install trap handler function (second-level trap handler).
96
101
*
97
102
* @param[in] id Identifier (type) of the targeted trap. See #NEORV32_RTE_TRAP_enum.
98
103
* @param[in] handler The actual handler function for the specified trap (function MUST be of type "void function(void);").
99
104
* @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.
100
107
**************************************************************************/
101
108
int neorv32_rte_handler_install (int id , void (* handler )(void )) {
102
109
110
+ // raise an exception if we're not in machine-mode
111
+ asm volatile ("csrr x0, mhartid" );
112
+
103
113
// id valid?
104
114
if ((id >= (int )RTE_TRAP_I_MISALIGNED ) && (id <= (int )RTE_TRAP_FIRQ_15 )) {
105
115
__neorv32_rte_vector_lut [id ] = (uint32_t )handler ; // install handler
@@ -110,15 +120,20 @@ int neorv32_rte_handler_install(int id, void (*handler)(void)) {
110
120
111
121
112
122
/**********************************************************************/ /**
113
- * NEORV32 runtime environment (RTE).
123
+ * NEORV32 runtime environment (RTE):
114
124
* Uninstall trap handler function from NEORV32 runtime environment, which was
115
125
* previously installed via neorv32_rte_handler_install(uint8_t id, void (*handler)(void)).
116
126
*
117
127
* @param[in] id Identifier (type) of the targeted trap. See #NEORV32_RTE_TRAP_enum.
118
128
* @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.
119
131
**************************************************************************/
120
132
int neorv32_rte_handler_uninstall (int id ) {
121
133
134
+ // raise an exception if we're not in machine-mode
135
+ asm volatile ("csrr x0, mhartid" );
136
+
122
137
// id valid?
123
138
if ((id >= (int )RTE_TRAP_I_MISALIGNED ) && (id <= (int )RTE_TRAP_FIRQ_15 )) {
124
139
__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) {
129
144
130
145
131
146
/**********************************************************************/ /**
132
- * NEORV32 runtime environment (RTE).
147
+ * NEORV32 runtime environment (RTE):
133
148
* This is the core of the NEORV32 RTE (first-level trap handler, executed in machine mode).
134
149
**************************************************************************/
135
150
static void __attribute__((__naked__ ,aligned (4 ))) __neorv32_rte_core (void ) {
136
151
137
152
// save context
138
- asm volatile (
153
+ asm volatile (
139
154
"csrw mscratch, sp \n" // backup original stack pointer
155
+
156
+ #ifndef __riscv_32e
140
157
"addi sp, sp, -32*4 \n"
158
+ #else
159
+ "addi sp, sp, -16*4 \n"
160
+ #endif
141
161
142
162
"sw x0, 0*4(sp) \n"
143
163
"sw x1, 1*4(sp) \n"
@@ -241,6 +261,7 @@ static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
241
261
asm volatile (
242
262
// "lw x0, 0*4(sp) \n"
243
263
"lw x1, 1*4(sp) \n"
264
+ // restore 2x at the very end
244
265
"lw x3, 3*4(sp) \n"
245
266
"lw x4, 4*4(sp) \n"
246
267
"lw x5, 5*4(sp) \n"
@@ -279,9 +300,11 @@ static void __attribute__((__naked__,aligned(4))) __neorv32_rte_core(void) {
279
300
280
301
281
302
/**********************************************************************/ /**
282
- * NEORV32 runtime environment:
303
+ * NEORV32 runtime environment (RTE) :
283
304
* Read register from application context.
284
305
*
306
+ * @warning This function can be called from machine-mode only.
307
+ *
285
308
* @param[in] x Register number (0..31, corresponds to register x0..x31).
286
309
* @return Content of register x.
287
310
**************************************************************************/
@@ -298,9 +321,11 @@ uint32_t neorv32_rte_context_get(int x) {
298
321
299
322
300
323
/**********************************************************************/ /**
301
- * NEORV32 runtime environment:
324
+ * NEORV32 runtime environment (RTE) :
302
325
* Write register in application context.
303
326
*
327
+ * @warning This function can be called from machine-mode only.
328
+ *
304
329
* @param[in] x Register number (0..31, corresponds to register x0..x31).
305
330
* @param[in] data Data to be written to register x.
306
331
**************************************************************************/
@@ -317,8 +342,8 @@ void neorv32_rte_context_put(int x, uint32_t data) {
317
342
318
343
319
344
/**********************************************************************/ /**
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 .
322
347
**************************************************************************/
323
348
static void __neorv32_rte_debug_handler (void ) {
324
349
@@ -403,17 +428,87 @@ static void __neorv32_rte_debug_handler(void) {
403
428
}
404
429
405
430
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
+
406
496
// #################################################################################################
407
497
// RTE Hardware Analysis Helpers
408
498
// #################################################################################################
409
499
410
500
411
501
/**********************************************************************/ /**
412
- * NEORV32 runtime environment:
502
+ * NEORV32 runtime environment (RTE) :
413
503
* Print hardware configuration information via UART0.
504
+ *
505
+ * @warning This function can be called from machine-mode only.
414
506
**************************************************************************/
415
507
void neorv32_rte_print_hw_config (void ) {
416
508
509
+ // raise an exception if we're not in machine-mode
510
+ asm volatile ("csrr x0, mhartid" );
511
+
417
512
if (neorv32_uart0_available () == 0 ) {
418
513
return ; // cannot output anything if UART0 is not implemented
419
514
}
@@ -618,7 +713,7 @@ void neorv32_rte_print_hw_config(void) {
618
713
619
714
620
715
/**********************************************************************/ /**
621
- * NEORV32 runtime environment:
716
+ * NEORV32 runtime environment (RTE) :
622
717
* Private function to print true or false via UART0.
623
718
*
624
719
* @param[in] state Print 'true' when !=0, print 'false' when 0
@@ -635,7 +730,7 @@ static void __neorv32_rte_print_true_false(int state) {
635
730
636
731
637
732
/**********************************************************************/ /**
638
- * NEORV32 runtime environment:
733
+ * NEORV32 runtime environment (RTE) :
639
734
* Private function to print 32-bit number as 8-digit hexadecimal value (with "0x" suffix).
640
735
*
641
736
* @param[in] num Number to print as hexadecimal via UART0.
@@ -660,8 +755,10 @@ void __neorv32_rte_print_hex_word(uint32_t num) {
660
755
661
756
662
757
/**********************************************************************/ /**
663
- * NEORV32 runtime environment:
758
+ * NEORV32 runtime environment (RTE) :
664
759
* Print the processor version in human-readable format via UART0.
760
+ *
761
+ * @warning This function can be called from machine-mode only.
665
762
**************************************************************************/
666
763
void neorv32_rte_print_hw_version (void ) {
667
764
@@ -695,7 +792,7 @@ void neorv32_rte_print_hw_version(void) {
695
792
696
793
697
794
/**********************************************************************/ /**
698
- * NEORV32 runtime environment:
795
+ * NEORV32 runtime environment (RTE) :
699
796
* Print project credits via UART0.
700
797
**************************************************************************/
701
798
void neorv32_rte_print_credits (void ) {
@@ -710,7 +807,7 @@ void neorv32_rte_print_credits(void) {
710
807
711
808
712
809
/**********************************************************************/ /**
713
- * NEORV32 runtime environment:
810
+ * NEORV32 runtime environment (RTE) :
714
811
* Print project logo via UART0.
715
812
**************************************************************************/
716
813
void neorv32_rte_print_logo (void ) {
@@ -754,7 +851,7 @@ void neorv32_rte_print_logo(void) {
754
851
755
852
756
853
/**********************************************************************/ /**
757
- * NEORV32 runtime environment:
854
+ * NEORV32 runtime environment (RTE) :
758
855
* Print project license via UART0.
759
856
**************************************************************************/
760
857
void neorv32_rte_print_license (void ) {
@@ -799,7 +896,7 @@ void neorv32_rte_print_license(void) {
799
896
800
897
801
898
/**********************************************************************/ /**
802
- * NEORV32 runtime environment:
899
+ * NEORV32 runtime environment (RTE) :
803
900
* Get MISA CSR value according to *compiler/toolchain configuration*.
804
901
*
805
902
* @return MISA content according to compiler configuration.
@@ -851,9 +948,11 @@ uint32_t neorv32_rte_get_compiler_isa(void) {
851
948
852
949
853
950
/**********************************************************************/ /**
854
- * NEORV32 runtime environment:
951
+ * NEORV32 runtime environment (RTE) :
855
952
* Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
856
953
*
954
+ * @warning This function can be called from machine-mode only.
955
+ *
857
956
* @param[in] silent Show error message (via UART0) if isa_sw > isa_hw when = 0.
858
957
* @return MISA content according to compiler configuration.
859
958
**************************************************************************/
0 commit comments