Line 151... |
Line 151... |
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* This global variable keeps the size of the available executable in bytes.
|
* This global variable keeps the size of the available executable in bytes.
|
* If =0 no executable is available (yet).
|
* If =0 no executable is available (yet).
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t exe_available = 0;
|
volatile uint32_t exe_available = 0;
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Only set during executable fetch (required for cpaturing STORE-BUS-TIMOUT exception).
|
|
**************************************************************************/
|
|
volatile uint32_t getting_exe = 0;
|
|
|
|
|
// Function prototypes
|
// Function prototypes
|
void __attribute__((__interrupt__)) bootloader_trap_handler(void);
|
void __attribute__((__interrupt__)) bootloader_trap_handler(void);
|
void fast_upload(int src);
|
void fast_upload(int src);
|
Line 185... |
Line 191... |
|
|
#ifdef __riscv_compressed
|
#ifdef __riscv_compressed
|
#warning In order to allow the bootloader to run on any CPU configuration it should be compiled using the base ISA (rv32i/e) only.
|
#warning In order to allow the bootloader to run on any CPU configuration it should be compiled using the base ISA (rv32i/e) only.
|
#endif
|
#endif
|
|
|
// global variable for executable size; 0 means there is no exe available
|
exe_available = 0; // global variable for executable size; 0 means there is no exe available
|
exe_available = 0;
|
getting_exe = 0; // we are not trying to get an executable yet
|
|
|
// ------------------------------------------------
|
|
// Minimal CPU hardware initialization
|
|
// - all IO devices are reset and disabled by the crt0 code
|
|
// ------------------------------------------------
|
|
|
|
// confiure trap handler (bare-metal, no neorv32 rte available)
|
|
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)(&bootloader_trap_handler));
|
|
|
|
|
|
// ------------------------------------------------
|
// ------------------------------------------------
|
// Minimal processor hardware initialization
|
// Minimal processor hardware initialization
|
// - all IO devices are reset and disabled by the crt0 code
|
// - all IO devices are reset and disabled by the crt0 code
|
// ------------------------------------------------
|
// ------------------------------------------------
|
Line 224... |
Line 221... |
neorv32_uart_setup(BAUD_RATE, 0, 0, 0);
|
neorv32_uart_setup(BAUD_RATE, 0, 0, 0);
|
|
|
// Configure machine system timer interrupt for ~2Hz
|
// Configure machine system timer interrupt for ~2Hz
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (clock_speed/4));
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (clock_speed/4));
|
|
|
|
// confiure trap handler (bare-metal, no neorv32 rte available)
|
|
neorv32_cpu_csr_write(CSR_MTVEC, (uint32_t)(&bootloader_trap_handler));
|
|
|
|
// active timer IRQ
|
neorv32_cpu_csr_write(CSR_MIE, 1 << CSR_MIE_MTIE); // activate MTIME IRQ source
|
neorv32_cpu_csr_write(CSR_MIE, 1 << CSR_MIE_MTIE); // activate MTIME IRQ source
|
neorv32_cpu_eint(); // enable global interrupts
|
neorv32_cpu_eint(); // enable global interrupts
|
|
|
|
|
// ------------------------------------------------
|
// ------------------------------------------------
|
Line 403... |
Line 404... |
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Bootloader trap handler. Used for the MTIME tick and to capture any other traps.
|
* Bootloader trap handler. Used for the MTIME tick and to capture any other traps.
|
* @warning Since we have no runtime environment, we have to use the interrupt attribute here. Here, and only here!
|
* @warning Since we have no runtime environment, we have to use the interrupt attribute here. Here and only here!
|
**************************************************************************/
|
**************************************************************************/
|
void __attribute__((__interrupt__)) bootloader_trap_handler(void) {
|
void __attribute__((__interrupt__)) bootloader_trap_handler(void) {
|
|
|
// make sure this was caused by MTIME IRQ
|
|
uint32_t cause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
uint32_t cause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
|
|
|
// make sure this was caused by MTIME IRQ
|
if (cause == TRAP_CODE_MTI) { // raw exception code for MTI
|
if (cause == TRAP_CODE_MTI) { // raw exception code for MTI
|
if (STATUS_LED_EN == 1) {
|
if (STATUS_LED_EN == 1) {
|
// toggle status LED
|
// toggle status LED
|
neorv32_gpio_pin_toggle(STATUS_LED);
|
neorv32_gpio_pin_toggle(STATUS_LED);
|
}
|
}
|
// set time for next IRQ
|
// set time for next IRQ
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
|
}
|
}
|
|
else {
|
else if (cause == TRAP_CODE_S_ACCESS) { // seems like executable is too large
|
// store bus access error during get_exe
|
|
// -> seems like executable is too large
|
|
if ((cause == TRAP_CODE_S_ACCESS) && (getting_exe)) {
|
system_error(ERROR_SIZE);
|
system_error(ERROR_SIZE);
|
}
|
}
|
|
// unknown error
|
else {
|
else {
|
neorv32_uart_print("\n\nEXC (");
|
neorv32_uart_print("\n\nEXC (");
|
print_hex_word(cause);
|
print_hex_word(cause);
|
neorv32_uart_print(") @ 0x");
|
neorv32_uart_print(") @ 0x");
|
print_hex_word(neorv32_cpu_csr_read(CSR_MEPC));
|
print_hex_word(neorv32_cpu_csr_read(CSR_MEPC));
|
system_error(ERROR_SYSTEM);
|
system_error(ERROR_SYSTEM);
|
}
|
}
|
}
|
}
|
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Get executable stream.
|
* Get executable stream.
|
*
|
*
|
* @param src Source of executable stream data. See #EXE_STREAM_SOURCE.
|
* @param src Source of executable stream data. See #EXE_STREAM_SOURCE.
|
**************************************************************************/
|
**************************************************************************/
|
void get_exe(int src) {
|
void get_exe(int src) {
|
|
|
|
getting_exe = 1; // to inform trap handler we were trying to get an executable
|
|
|
// is MEM implemented and read-only?
|
// is MEM implemented and read-only?
|
if ((SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) &&
|
if ((SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) &&
|
(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM))) {
|
(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM))) {
|
system_error(ERROR_ROM);
|
system_error(ERROR_ROM);
|
}
|
}
|
Line 491... |
Line 498... |
}
|
}
|
else {
|
else {
|
neorv32_uart_print("OK");
|
neorv32_uart_print("OK");
|
exe_available = size; // store exe size
|
exe_available = size; // store exe size
|
}
|
}
|
|
|
|
getting_exe = 0; // to inform trap handler we are done getting an executable
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Store content of instruction memory to SPI flash.
|
* Store content of instruction memory to SPI flash.
|