Line 77... |
Line 77... |
#define SPI_FLASH_CS (0)
|
#define SPI_FLASH_CS (0)
|
/** Default SPI flash clock prescaler */
|
/** Default SPI flash clock prescaler */
|
#define SPI_FLASH_CLK_PRSC (CLK_PRSC_8)
|
#define SPI_FLASH_CLK_PRSC (CLK_PRSC_8)
|
/** SPI flash sector size in bytes (default = 64kb) */
|
/** SPI flash sector size in bytes (default = 64kb) */
|
#define SPI_FLASH_SECTOR_SIZE (64*1024)
|
#define SPI_FLASH_SECTOR_SIZE (64*1024)
|
|
/** ASCII char to start fast executable upload process (for use with automatic upload scripts) */
|
|
#define FAST_UPLOAD_CMD '#'
|
/**@}*/
|
/**@}*/
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
Executable stream source select
|
Executable stream source select
|
Line 152... |
Line 154... |
uint32_t exe_available = 0;
|
uint32_t exe_available = 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 print_help(void);
|
void print_help(void);
|
void start_app(void);
|
void start_app(void);
|
void get_exe(int src);
|
void get_exe(int src);
|
void save_exe(void);
|
void save_exe(void);
|
uint32_t get_exe_word(int src, uint32_t addr);
|
uint32_t get_exe_word(int src, uint32_t addr);
|
Line 248... |
Line 251... |
uint64_t timeout_time = neorv32_mtime_get_time() + (uint64_t)(AUTOBOOT_TIMEOUT * clock_speed);
|
uint64_t timeout_time = neorv32_mtime_get_time() + (uint64_t)(AUTOBOOT_TIMEOUT * clock_speed);
|
|
|
while ((UART_DATA & (1 << UART_DATA_AVAIL)) == 0) { // wait for any key to be pressed
|
while ((UART_DATA & (1 << UART_DATA_AVAIL)) == 0) { // wait for any key to be pressed
|
|
|
if (neorv32_mtime_get_time() >= timeout_time) { // timeout? start auto boot sequence
|
if (neorv32_mtime_get_time() >= timeout_time) { // timeout? start auto boot sequence
|
get_exe(EXE_STREAM_FLASH); // try loading from spi flash
|
fast_upload(EXE_STREAM_FLASH); // try booting from flash
|
neorv32_uart_print("\n");
|
|
start_app();
|
|
}
|
}
|
}
|
}
|
neorv32_uart_print("Aborted.\n\n");
|
neorv32_uart_print("Aborted.\n\n");
|
|
|
|
// fast executable upload?
|
|
if (neorv32_uart_char_received_get() == FAST_UPLOAD_CMD) {
|
|
fast_upload(EXE_STREAM_UART);
|
|
}
|
#else
|
#else
|
neorv32_uart_print("\n\n");
|
neorv32_uart_print("\n\n");
|
#endif
|
#endif
|
|
|
print_help();
|
print_help();
|
Line 271... |
Line 277... |
neorv32_uart_print("\nCMD:> ");
|
neorv32_uart_print("\nCMD:> ");
|
char c = neorv32_uart_getc();
|
char c = neorv32_uart_getc();
|
neorv32_uart_putc(c); // echo
|
neorv32_uart_putc(c); // echo
|
neorv32_uart_print("\n");
|
neorv32_uart_print("\n");
|
|
|
if (c == 'r') { // restart bootloader
|
if (c == FAST_UPLOAD_CMD) { // fast executable upload
|
neorv32_cpu_dint(); // disable global interrupts
|
fast_upload(EXE_STREAM_UART);
|
|
}
|
|
else if (c == 'r') { // restart bootloader
|
asm volatile ("li t0, %[input_i]; jr t0" : : [input_i] "i" (BOOTLOADER_BASE_ADDRESS)); // jump to beginning of boot ROM
|
asm volatile ("li t0, %[input_i]; jr t0" : : [input_i] "i" (BOOTLOADER_BASE_ADDRESS)); // jump to beginning of boot ROM
|
while(1); // just for the compiler
|
|
}
|
}
|
else if (c == 'h') { // help menu
|
else if (c == 'h') { // help menu
|
print_help();
|
print_help();
|
}
|
}
|
else if (c == 'u') { // get executable via UART
|
else if (c == 'u') { // get executable via UART
|
Line 304... |
Line 311... |
return 0; // bootloader should never return
|
return 0; // bootloader should never return
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
|
* Get executable stream and execute it.
|
|
*
|
|
* @param src Source of executable stream data. See #EXE_STREAM_SOURCE.
|
|
**************************************************************************/
|
|
void fast_upload(int src) {
|
|
|
|
get_exe(src);
|
|
neorv32_uart_print("\n");
|
|
start_app();
|
|
while(1);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
* Print help menu.
|
* Print help menu.
|
**************************************************************************/
|
**************************************************************************/
|
void print_help(void) {
|
void print_help(void) {
|
|
|
neorv32_uart_print("Available CMDs:\n"
|
neorv32_uart_print("Available CMDs:\n"
|
Line 376... |
Line 397... |
else if (cause == TRAP_CODE_S_ACCESS) { // seems like executable is too large
|
else if (cause == TRAP_CODE_S_ACCESS) { // seems like executable is too large
|
system_error(ERROR_SIZE);
|
system_error(ERROR_SIZE);
|
}
|
}
|
|
|
else {
|
else {
|
neorv32_uart_print("\n\nEXCEPTION (");
|
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);
|
}
|
}
|
Line 559... |
Line 580... |
neorv32_cpu_dint(); // deactivate IRQs
|
neorv32_cpu_dint(); // deactivate IRQs
|
if (STATUS_LED_EN == 1) {
|
if (STATUS_LED_EN == 1) {
|
neorv32_gpio_port_set(1 << STATUS_LED); // permanently light up status LED
|
neorv32_gpio_port_set(1 << STATUS_LED); // permanently light up status LED
|
}
|
}
|
|
|
asm volatile ("wfi"); // power-down
|
|
while(1); // freeze
|
while(1); // freeze
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|