Line 67... |
Line 67... |
#define AUTOBOOT_EN (1)
|
#define AUTOBOOT_EN (1)
|
/** Time until the auto-boot sequence starts (in seconds) */
|
/** Time until the auto-boot sequence starts (in seconds) */
|
#define AUTOBOOT_TIMEOUT 8
|
#define AUTOBOOT_TIMEOUT 8
|
/** Set to 0 to disable bootloader status LED */
|
/** Set to 0 to disable bootloader status LED */
|
#define STATUS_LED_EN (1)
|
#define STATUS_LED_EN (1)
|
|
/** SPI_DIRECT_BOOT_EN: Define/uncomment to enable SPI direct boot (disables the entire user console!) */
|
|
//#define SPI_DIRECT_BOOT_EN
|
/** Bootloader status LED at GPIO output port */
|
/** Bootloader status LED at GPIO output port */
|
#define STATUS_LED (0)
|
#define STATUS_LED (0)
|
/** SPI flash boot image base address (warning! address might wrap-around!) */
|
/** SPI flash boot image base address (warning! address might wrap-around!) */
|
#define SPI_FLASH_BOOT_ADR (0x00800000)
|
#define SPI_FLASH_BOOT_ADR (0x00800000)
|
/** SPI flash chip select line at spi_csn_o */
|
/** SPI flash chip select line at spi_csn_o */
|
Line 179... |
Line 181... |
/**********************************************************************//**
|
/**********************************************************************//**
|
* Bootloader main.
|
* Bootloader main.
|
**************************************************************************/
|
**************************************************************************/
|
int main(void) {
|
int main(void) {
|
|
|
|
#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.
|
|
#endif
|
|
|
|
// global variable for executable size; 0 means there is no exe available
|
|
exe_available = 0;
|
|
|
|
// ------------------------------------------------
|
|
// 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));
|
|
|
|
|
// ------------------------------------------------
|
// ------------------------------------------------
|
// 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
|
// ------------------------------------------------
|
// ------------------------------------------------
|
|
|
// get clock speed (in Hz)
|
// get clock speed (in Hz)
|
uint32_t clock_speed = SYSINFO_CLK;
|
uint32_t clock_speed = SYSINFO_CLK;
|
Line 195... |
Line 213... |
}
|
}
|
else {
|
else {
|
neorv32_spi_setup(CLK_PRSC_128, 0, 0, 0);
|
neorv32_spi_setup(CLK_PRSC_128, 0, 0, 0);
|
}
|
}
|
|
|
|
if (STATUS_LED_EN == 1) {
|
|
// activate status LED, clear all others
|
|
neorv32_gpio_port_set(1 << STATUS_LED);
|
|
}
|
|
|
// init UART (no interrupts)
|
// init UART (no interrupts)
|
neorv32_uart_setup(BAUD_RATE, 0, 0);
|
neorv32_uart_setup(BAUD_RATE, 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));
|
|
|
|
neorv32_cpu_csr_write(CSR_MIE, 1 << CPU_MIE_MTIE); // activate MTIME IRQ source
|
neorv32_cpu_csr_write(CSR_MIE, 1 << CPU_MIE_MTIE); // activate MTIME IRQ source
|
neorv32_cpu_eint(); // enable global interrupts
|
neorv32_cpu_eint(); // enable global interrupts
|
|
|
if (STATUS_LED_EN == 1) {
|
|
// activate status LED, clear all others
|
|
neorv32_gpio_port_set(1 << STATUS_LED);
|
|
}
|
|
|
|
// global variable to executable size; 0 means there is no exe available
|
// ------------------------------------------------
|
exe_available = 0;
|
// Fast boot mode: Direct SPI boot
|
|
// Bootloader will directly boot and execute image from SPI memory.
|
|
// No user UART console is available in this mode!
|
|
// ------------------------------------------------
|
|
#ifdef SPI_DIRECT_BOOT_EN
|
|
#warning Compiling bootloader in 'SPI direct boot mode'. Bootloader will directly boot from SPI memory. No user UART console will be available.
|
|
|
|
neorv32_uart_print("\nNEORV32 bootloader\nAccessing SPI flash at ");
|
|
print_hex_word((uint32_t)SPI_FLASH_BOOT_ADR);
|
|
neorv32_uart_print("\n");
|
|
|
|
get_exe(EXE_STREAM_FLASH);
|
|
neorv32_uart_print("\n");
|
|
start_app();
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
|
// ------------------------------------------------
|
// ------------------------------------------------
|
// Show bootloader intro and system info
|
// Show bootloader intro and system info
|
// ------------------------------------------------
|
// ------------------------------------------------
|
Line 350... |
Line 382... |
if (exe_available == 0) {
|
if (exe_available == 0) {
|
neorv32_uart_print("No executable available.");
|
neorv32_uart_print("No executable available.");
|
return;
|
return;
|
}
|
}
|
|
|
// no need to shut down or reset the used peripherals
|
// no need to shut down/reset the used peripherals
|
// no need to disable interrupt sources
|
// no need to disable interrupt sources
|
// -> this will be done by application's crt0
|
// -> crt0 will do a clean CPU/processor reset/setup
|
|
|
// deactivate global IRQs
|
// deactivate global IRQs
|
neorv32_cpu_dint();
|
neorv32_cpu_dint();
|
|
|
neorv32_uart_print("Booting...\n\n");
|
neorv32_uart_print("Booting...\n\n");
|
|
|
// wait for UART to finish transmitting
|
// wait for UART to finish transmitting
|
while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
|
while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
|
|
|
// reset performance counters (to benchmark actual application)
|
|
asm volatile ("csrw mcycle, zero"); // also clears 'cycle'
|
|
asm volatile ("csrw mcycleh, zero"); // also clears 'cycleh'
|
|
asm volatile ("csrw minstret, zero"); // also clears 'instret'
|
|
asm volatile ("csrw minstreth, zero"); // also clears 'instreth'
|
|
|
|
// start app at instruction space base address
|
// start app at instruction space base address
|
register uint32_t app_base = SYSINFO_ISPACE_BASE;
|
register uint32_t app_base = SYSINFO_ISPACE_BASE;
|
asm volatile ("jalr zero, %0" : : "r" (app_base));
|
asm volatile ("jalr zero, %0" : : "r" (app_base));
|
while (1);
|
while (1);
|
}
|
}
|
Line 666... |
Line 692... |
uint8_t uint8[sizeof(uint32_t)];
|
uint8_t uint8[sizeof(uint32_t)];
|
} data;
|
} data;
|
|
|
data.uint32 = wdata;
|
data.uint32 = wdata;
|
|
|
uint32_t i;
|
int i;
|
for (i=0; i<4; i++) {
|
for (i=0; i<4; i++) {
|
spi_flash_write_byte(addr + i, data.uint8[3-i]);
|
spi_flash_write_byte(addr + i, data.uint8[3-i]);
|
}
|
}
|
}
|
}
|
|
|
Line 759... |
Line 785... |
uint8_t uint8[sizeof(uint32_t)];
|
uint8_t uint8[sizeof(uint32_t)];
|
} address;
|
} address;
|
|
|
address.uint32 = addr;
|
address.uint32 = addr;
|
|
|
neorv32_spi_trans(address.uint8[2]);
|
int i;
|
neorv32_spi_trans(address.uint8[1]);
|
for (i=2; i>=0; i--) {
|
neorv32_spi_trans(address.uint8[0]);
|
neorv32_spi_trans(address.uint8[i]);
|
|
}
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|