Line 49... |
Line 49... |
|
|
// 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(16)));
|
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_hex_word(uint32_t num);
|
static void __neorv32_rte_print_hex_word(uint32_t num);
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Setup NEORV32 runtime environment.
|
* Setup NEORV32 runtime environment.
|
Line 202... |
Line 203... |
}
|
}
|
|
|
char tmp;
|
char tmp;
|
|
|
// intro
|
// intro
|
neorv32_uart_print("<RTE> ");
|
neorv32_uart0_print("<RTE> ");
|
|
|
// cause
|
// cause
|
register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
tmp = (char)(trap_cause & 0xf);
|
tmp = (char)(trap_cause & 0xf);
|
if (tmp >= 10) {
|
if (tmp >= 10) {
|
Line 214... |
Line 215... |
}
|
}
|
else {
|
else {
|
tmp = '0' + tmp;
|
tmp = '0' + tmp;
|
}
|
}
|
switch (trap_cause) {
|
switch (trap_cause) {
|
case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break;
|
case TRAP_CODE_I_MISALIGNED: neorv32_uart0_print("Instruction address misaligned"); break;
|
case TRAP_CODE_I_ACCESS: neorv32_uart_print("Instruction access fault"); break;
|
case TRAP_CODE_I_ACCESS: neorv32_uart0_print("Instruction access fault"); break;
|
case TRAP_CODE_I_ILLEGAL: neorv32_uart_print("Illegal instruction"); break;
|
case TRAP_CODE_I_ILLEGAL: neorv32_uart0_print("Illegal instruction"); break;
|
case TRAP_CODE_BREAKPOINT: neorv32_uart_print("Breakpoint"); break;
|
case TRAP_CODE_BREAKPOINT: neorv32_uart0_print("Breakpoint"); break;
|
case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break;
|
case TRAP_CODE_L_MISALIGNED: neorv32_uart0_print("Load address misaligned"); break;
|
case TRAP_CODE_L_ACCESS: neorv32_uart_print("Load access fault"); break;
|
case TRAP_CODE_L_ACCESS: neorv32_uart0_print("Load access fault"); break;
|
case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break;
|
case TRAP_CODE_S_MISALIGNED: neorv32_uart0_print("Store address misaligned"); break;
|
case TRAP_CODE_S_ACCESS: neorv32_uart_print("Store access fault"); break;
|
case TRAP_CODE_S_ACCESS: neorv32_uart0_print("Store access fault"); break;
|
case TRAP_CODE_UENV_CALL: neorv32_uart_print("Environment call from U-mode"); break;
|
case TRAP_CODE_UENV_CALL: neorv32_uart0_print("Environment call from U-mode"); break;
|
case TRAP_CODE_MENV_CALL: neorv32_uart_print("Environment call from M-mode"); break;
|
case TRAP_CODE_MENV_CALL: neorv32_uart0_print("Environment call from M-mode"); break;
|
case TRAP_CODE_MSI: neorv32_uart_print("Machine software interrupt"); break;
|
case TRAP_CODE_MSI: neorv32_uart0_print("Machine software interrupt"); break;
|
case TRAP_CODE_MTI: neorv32_uart_print("Machine timer interrupt"); break;
|
case TRAP_CODE_MTI: neorv32_uart0_print("Machine timer interrupt"); break;
|
case TRAP_CODE_MEI: neorv32_uart_print("Machine external interrupt"); break;
|
case TRAP_CODE_MEI: neorv32_uart0_print("Machine external interrupt"); break;
|
case TRAP_CODE_FIRQ_0:
|
case TRAP_CODE_FIRQ_0:
|
case TRAP_CODE_FIRQ_1:
|
case TRAP_CODE_FIRQ_1:
|
case TRAP_CODE_FIRQ_2:
|
case TRAP_CODE_FIRQ_2:
|
case TRAP_CODE_FIRQ_3:
|
case TRAP_CODE_FIRQ_3:
|
case TRAP_CODE_FIRQ_4:
|
case TRAP_CODE_FIRQ_4:
|
Line 242... |
Line 243... |
case TRAP_CODE_FIRQ_10:
|
case TRAP_CODE_FIRQ_10:
|
case TRAP_CODE_FIRQ_11:
|
case TRAP_CODE_FIRQ_11:
|
case TRAP_CODE_FIRQ_12:
|
case TRAP_CODE_FIRQ_12:
|
case TRAP_CODE_FIRQ_13:
|
case TRAP_CODE_FIRQ_13:
|
case TRAP_CODE_FIRQ_14:
|
case TRAP_CODE_FIRQ_14:
|
case TRAP_CODE_FIRQ_15: neorv32_uart_print("Fast interrupt "); neorv32_uart_putc(tmp); break;
|
case TRAP_CODE_FIRQ_15: neorv32_uart0_print("Fast interrupt "); neorv32_uart0_putc(tmp); break;
|
default: neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
|
default: neorv32_uart0_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
|
}
|
}
|
|
|
// instruction address
|
// instruction address
|
neorv32_uart_print(" @ PC=");
|
neorv32_uart0_print(" @ PC=");
|
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
|
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
|
|
|
// additional info
|
// additional info
|
neorv32_uart_print(", MTVAL=");
|
neorv32_uart0_print(", MTVAL=");
|
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
|
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
|
neorv32_uart_print(" </RTE>");
|
neorv32_uart0_print(" </RTE>");
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* NEORV32 runtime environment: Print hardware configuration information via UART
|
* NEORV32 runtime environment: Print hardware configuration information via UART
|
Line 270... |
Line 271... |
|
|
uint32_t tmp;
|
uint32_t tmp;
|
int i;
|
int i;
|
char c;
|
char c;
|
|
|
neorv32_uart_printf("\n\n<<< Processor Configuration Overview >>>\n");
|
neorv32_uart0_printf("\n\n<<< Processor Configuration Overview >>>\n");
|
|
|
// Processor - general stuff
|
|
neorv32_uart0_printf("\n=== << General >> ===\n"
|
|
"Clock speed: %u Hz\n", NEORV32_SYSINFO.CLK);
|
|
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
|
|
neorv32_uart0_printf("Boot Config.: Boot ");
|
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
|
|
neorv32_uart0_printf("via Bootloader\n");
|
|
}
|
|
else {
|
|
neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
|
|
}
|
|
neorv32_uart0_printf("On-chip debug: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
|
|
|
|
|
|
// CPU configuration
|
// CPU configuration
|
neorv32_uart0_printf("\n=== << CPU >> ===\n");
|
neorv32_uart0_printf("\n=== << CPU >> ===\n");
|
|
|
|
// general
|
|
neorv32_uart0_printf("Clock speed: %u Hz\n", NEORV32_SYSINFO.CLK);
|
|
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
|
|
neorv32_uart0_printf("On-chip debugger: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
|
// ID
|
// ID
|
neorv32_uart0_printf("Hart ID: 0x%x\n"
|
neorv32_uart0_printf("Hart ID: 0x%x\n"
|
"Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
|
"Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
|
|
|
tmp = neorv32_cpu_csr_read(CSR_MARCHID);
|
tmp = neorv32_cpu_csr_read(CSR_MARCHID);
|
Line 376... |
Line 367... |
// check hardware performance monitors
|
// check hardware performance monitors
|
neorv32_uart0_printf("HPM Counters: %u counters, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size());
|
neorv32_uart0_printf("HPM Counters: %u counters, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size());
|
|
|
|
|
// Memory configuration
|
// Memory configuration
|
neorv32_uart0_printf("\n=== << Memory Configuration >> ===\n");
|
neorv32_uart0_printf("\n=== << Memory System >> ===\n");
|
|
|
|
neorv32_uart0_printf("Boot Config.: Boot ");
|
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
|
|
neorv32_uart0_printf("via Bootloader\n");
|
|
}
|
|
else {
|
|
neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
|
|
}
|
|
|
neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
|
neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
|
|
|
// IMEM
|
// IMEM
|
neorv32_uart0_printf("Internal IMEM: ");
|
neorv32_uart0_printf("Internal IMEM: ");
|
Line 392... |
Line 391... |
}
|
}
|
|
|
// DMEM
|
// DMEM
|
neorv32_uart0_printf("Data base address: 0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
|
neorv32_uart0_printf("Data base address: 0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
|
neorv32_uart0_printf("Internal DMEM: ");
|
neorv32_uart0_printf("Internal DMEM: ");
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) { neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE); }
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) {
|
else { neorv32_uart0_printf("no\n"); }
|
neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE);
|
|
}
|
|
else {
|
|
neorv32_uart0_printf("no\n");
|
|
}
|
|
|
// i-cache
|
// i-cache
|
neorv32_uart0_printf("Internal i-cache: ");
|
neorv32_uart0_printf("Internal i-cache: ");
|
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE));
|
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
|
neorv32_uart0_printf("- ");
|
neorv32_uart0_printf("yes, ");
|
|
|
uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
|
uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
|
if (ic_block_size) {
|
if (ic_block_size) {
|
ic_block_size = 1 << ic_block_size;
|
ic_block_size = 1 << ic_block_size;
|
}
|
}
|
Line 420... |
Line 422... |
}
|
}
|
|
|
uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
|
uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
|
ic_associativity = 1 << ic_associativity;
|
ic_associativity = 1 << ic_associativity;
|
|
|
neorv32_uart0_printf("%u bytes: %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size);
|
neorv32_uart0_printf("%u bytes, %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size);
|
if (ic_associativity == 1) {
|
if (ic_associativity == 1) {
|
neorv32_uart0_printf(" (direct-mapped)\n");
|
neorv32_uart0_printf(" (direct-mapped)\n");
|
}
|
}
|
else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
|
else if (((NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
|
neorv32_uart0_printf(" (LRU replacement policy)\n");
|
neorv32_uart0_printf(" (LRU replacement policy)\n");
|
}
|
}
|
else {
|
else {
|
neorv32_uart0_printf("\n");
|
neorv32_uart0_printf("\n");
|
}
|
}
|
}
|
}
|
|
else {
|
|
neorv32_uart0_printf("no\n");
|
|
}
|
|
|
neorv32_uart0_printf("Ext. bus interface: ");
|
neorv32_uart0_printf("Ext. bus interface: ");
|
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
|
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
|
neorv32_uart0_printf("Ext. bus Endianness: ");
|
neorv32_uart0_printf("Ext. bus Endianness: ");
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
|
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
|
Line 446... |
Line 451... |
|
|
// peripherals
|
// peripherals
|
neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
|
neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
|
|
|
tmp = NEORV32_SYSINFO.SOC;
|
tmp = NEORV32_SYSINFO.SOC;
|
neorv32_uart0_printf("GPIO - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_GPIO));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO)); neorv32_uart0_printf(" GPIO\n");
|
neorv32_uart0_printf("MTIME - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_MTIME));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME)); neorv32_uart0_printf(" MTIME\n");
|
neorv32_uart0_printf("UART0 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART0));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0)); neorv32_uart0_printf(" UART0\n");
|
neorv32_uart0_printf("UART1 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART1));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1)); neorv32_uart0_printf(" UART1\n");
|
neorv32_uart0_printf("SPI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SPI));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI)); neorv32_uart0_printf(" SPI\n");
|
neorv32_uart0_printf("TWI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TWI));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI)); neorv32_uart0_printf(" TWI\n");
|
neorv32_uart0_printf("PWM - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_PWM));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM)); neorv32_uart0_printf(" PWM\n");
|
neorv32_uart0_printf("WDT - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_WDT));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT)); neorv32_uart0_printf(" WDT\n");
|
neorv32_uart0_printf("TRNG - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TRNG));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG)); neorv32_uart0_printf(" TRNG\n");
|
neorv32_uart0_printf("CFS - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_CFS));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS)); neorv32_uart0_printf(" CFS\n");
|
neorv32_uart0_printf("SLINK - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SLINK));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK)); neorv32_uart0_printf(" SLINK\n");
|
neorv32_uart0_printf("NEOLED - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_NEOLED));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n");
|
neorv32_uart0_printf("XIRQ - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_XIRQ));
|
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ)); neorv32_uart0_printf(" XIRQ\n");
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* NEORV32 runtime environment: Private function to print yes or no.
|
* NEORV32 runtime environment: Private function to print yes or no.
|
* @note This function is used by neorv32_rte_print_hw_config(void) only.
|
* @note This function is used by neorv32_rte_print_hw_config(void) only.
|
*
|
*
|
* @param[in] state Print 'yes' when !=0, print '0' when 0
|
* @param[in] state Print 'yes' when !=0, print 'no' when 0
|
**************************************************************************/
|
**************************************************************************/
|
static void __neorv32_rte_print_true_false(int state) {
|
static void __neorv32_rte_print_true_false(int state) {
|
|
|
if (state) {
|
if (state) {
|
neorv32_uart0_print("yes\n");
|
neorv32_uart0_print("yes\n");
|
Line 480... |
Line 485... |
}
|
}
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
|
* NEORV32 runtime environment: Private function to print [x] or [ ].
|
|
* @note This function is used by neorv32_rte_print_hw_config(void) only.
|
|
*
|
|
* @param[in] state Print '[x]' when !=0, print '[ ]' when 0
|
|
**************************************************************************/
|
|
static void __neorv32_rte_print_checkbox(int state) {
|
|
|
|
neorv32_uart0_putc('[');
|
|
if (state) {
|
|
neorv32_uart0_putc('x');
|
|
}
|
|
else {
|
|
neorv32_uart0_putc(' ');
|
|
}
|
|
neorv32_uart0_putc(']');
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
* NEORV32 runtime environment: Private function to print 32-bit number
|
* NEORV32 runtime environment: Private function to print 32-bit number
|
* as 8-digit hexadecimal value (with "0x" suffix).
|
* as 8-digit hexadecimal value (with "0x" suffix).
|
*
|
*
|
* @param[in] num Number to print as hexadecimal.
|
* @param[in] num Number to print as hexadecimal.
|
**************************************************************************/
|
**************************************************************************/
|
Line 604... |
Line 628... |
|
|
if (neorv32_uart0_available() == 0) {
|
if (neorv32_uart0_available() == 0) {
|
return; // cannot output anything if UART0 is not implemented
|
return; // cannot output anything if UART0 is not implemented
|
}
|
}
|
|
|
neorv32_uart_print(
|
neorv32_uart0_print(
|
"\n"
|
"\n"
|
"BSD 3-Clause License\n"
|
"BSD 3-Clause License\n"
|
"\n"
|
"\n"
|
"Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
|
"Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
|
"\n"
|
"\n"
|
Line 710... |
Line 734... |
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_uart_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;
|
}
|
}
|