Line 46... |
Line 46... |
* The >private< trap vector look-up table of the NEORV32 RTE.
|
* The >private< trap vector look-up table of the NEORV32 RTE.
|
**************************************************************************/
|
**************************************************************************/
|
static uint32_t __neorv32_rte_vector_lut[NEORV32_RTE_NUM_TRAPS] __attribute__((unused)); // trap handler vector table
|
static uint32_t __neorv32_rte_vector_lut[NEORV32_RTE_NUM_TRAPS] __attribute__((unused)); // trap handler vector table
|
|
|
// private functions
|
// private functions
|
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16)));
|
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(4)));
|
static void __neorv32_rte_debug_exc_handler(void);
|
static void __neorv32_rte_debug_exc_handler(void);
|
static void __neorv32_rte_print_true_false(int state);
|
static void __neorv32_rte_print_true_false(int state);
|
static void __neorv32_rte_print_checkbox(int state);
|
static void __neorv32_rte_print_checkbox(int state);
|
static void __neorv32_rte_print_hex_word(uint32_t num);
|
static void __neorv32_rte_print_hex_word(uint32_t num);
|
|
|
Line 63... |
Line 63... |
* via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
|
* via neorv32_rte_exception_install(uint8_t id, void (*handler)(void)).
|
**************************************************************************/
|
**************************************************************************/
|
void neorv32_rte_setup(void) {
|
void neorv32_rte_setup(void) {
|
|
|
// configure trap handler base address
|
// configure trap handler base address
|
uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
|
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)(&__neorv32_rte_core));
|
neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
|
|
|
|
// install debug handler for all sources
|
// install debug handler for all sources
|
uint8_t id;
|
uint8_t id;
|
for (id = 0; id < (sizeof(__neorv32_rte_vector_lut)/sizeof(__neorv32_rte_vector_lut[0])); id++) {
|
for (id = 0; id < (sizeof(__neorv32_rte_vector_lut)/sizeof(__neorv32_rte_vector_lut[0])); id++) {
|
neorv32_rte_exception_uninstall(id); // this will configure the debug handler
|
neorv32_rte_exception_uninstall(id); // this will configure the debug handler
|
}
|
}
|
|
|
|
// clear BUSKEEPER error flags
|
|
NEORV32_BUSKEEPER.CTRL = 0;
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Install exception handler function to NEORV32 runtime environment.
|
* Install exception handler function to NEORV32 runtime environment.
|
Line 109... |
Line 111... |
**************************************************************************/
|
**************************************************************************/
|
int neorv32_rte_exception_uninstall(uint8_t id) {
|
int neorv32_rte_exception_uninstall(uint8_t id) {
|
|
|
// id valid?
|
// id valid?
|
if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
|
if ((id >= RTE_TRAP_I_MISALIGNED) && (id <= CSR_MIE_FIRQ15E)) {
|
__neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_exc_handler); // use dummy handler in case the exception is accidently triggered
|
__neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_exc_handler); // use dummy handler in case the exception is accidentally triggered
|
return 0;
|
return 0;
|
}
|
}
|
return 1;
|
return 1;
|
}
|
}
|
|
|
Line 124... |
Line 126... |
* @note This function must no be explicitly used by the user.
|
* @note This function must no be explicitly used by the user.
|
* @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
|
* @note The RTE core uses mscratch CSR to store the trap-causing mepc for further (user-defined) processing.
|
*
|
*
|
* @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
|
* @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
|
**************************************************************************/
|
**************************************************************************/
|
static void __attribute__((__interrupt__)) __attribute__((aligned(16))) __neorv32_rte_core(void) {
|
static void __attribute__((__interrupt__)) __attribute__((aligned(4))) __neorv32_rte_core(void) {
|
|
|
register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
|
register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
|
neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
|
neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
|
register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
|
|
// compute return address
|
// compute return address
|
if (((int32_t)rte_mcause) >= 0) { // modify pc only if exception (MSB cleared)
|
if (((int32_t)rte_mcause) >= 0) { // modify pc only if not interrupt (MSB cleared)
|
|
|
// get low half word of faulting instruction
|
// get low half word of faulting instruction
|
register uint32_t rte_trap_inst;
|
register uint32_t rte_trap_inst;
|
asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
|
asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
|
|
|
Line 149... |
Line 151... |
// store new return address
|
// store new return address
|
neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
|
neorv32_cpu_csr_write(CSR_MEPC, rte_mepc);
|
}
|
}
|
|
|
// find according trap handler
|
// find according trap handler
|
register uint32_t rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler);
|
register uint32_t rte_handler;
|
switch (rte_mcause) {
|
switch (rte_mcause) {
|
case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
|
case TRAP_CODE_I_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_MISALIGNED]; break;
|
case TRAP_CODE_I_ACCESS: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
|
case TRAP_CODE_I_ACCESS: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ACCESS]; break;
|
case TRAP_CODE_I_ILLEGAL: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
|
case TRAP_CODE_I_ILLEGAL: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_I_ILLEGAL]; break;
|
case TRAP_CODE_BREAKPOINT: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
|
case TRAP_CODE_BREAKPOINT: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_BREAKPOINT]; break;
|
Line 180... |
Line 182... |
case TRAP_CODE_FIRQ_11: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_11]; break;
|
case TRAP_CODE_FIRQ_11: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_11]; break;
|
case TRAP_CODE_FIRQ_12: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_12]; break;
|
case TRAP_CODE_FIRQ_12: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_12]; break;
|
case TRAP_CODE_FIRQ_13: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_13]; break;
|
case TRAP_CODE_FIRQ_13: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_13]; break;
|
case TRAP_CODE_FIRQ_14: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_14]; break;
|
case TRAP_CODE_FIRQ_14: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_14]; break;
|
case TRAP_CODE_FIRQ_15: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_15]; break;
|
case TRAP_CODE_FIRQ_15: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_15]; break;
|
default: break;
|
default: rte_handler = (uint32_t)(&__neorv32_rte_debug_exc_handler); break;
|
}
|
}
|
|
|
// execute handler
|
// execute handler
|
void (*handler_pnt)(void);
|
void (*handler_pnt)(void);
|
handler_pnt = (void*)rte_handler;
|
handler_pnt = (void*)rte_handler;
|
Line 728... |
Line 730... |
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
|
* NEORV32 runtime environment: Check required ISA extensions (via compiler flags) against available ISA extensions (via MISA csr).
|
*
|
*
|
* @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when != 0.
|
* @param[in] silent Show error message (via neorv32.uart) if isa_sw > isa_hw when = 0.
|
* @return MISA content according to compiler configuration.
|
* @return MISA content according to compiler configuration.
|
**************************************************************************/
|
**************************************************************************/
|
int neorv32_rte_check_isa(int silent) {
|
int neorv32_rte_check_isa(int silent) {
|
|
|
uint32_t misa_sw = neorv32_rte_get_compiler_isa();
|
uint32_t misa_sw = neorv32_rte_get_compiler_isa();
|
Line 744... |
Line 746... |
//
|
//
|
if (check == misa_sw) {
|
if (check == misa_sw) {
|
return 0;
|
return 0;
|
}
|
}
|
else {
|
else {
|
if ((silent == 0) || (neorv32_uart0_available() == 0)) {
|
if ((silent == 0) && (neorv32_uart0_available() != 0)) {
|
neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
|
neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
|
"SW_ISA = 0x%x (compiler flags)\n"
|
"SW_ISA = 0x%x (compiler flags)\n"
|
"HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
|
"HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
|
}
|
}
|
return 1;
|
return 1;
|