OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [bootloader/] [bootloader.c] - Diff between revs 11 and 12

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 11 Rev 12
Line 147... Line 147...
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);
void system_error(uint8_t err_code);
void system_error(uint8_t err_code);
void print_hex_word(uint32_t num);
void print_hex_word(uint32_t num);
void print_proc_version(void);
 
 
 
// SPI flash access
// SPI flash access
uint8_t spi_flash_read_byte(uint32_t addr);
uint8_t spi_flash_read_byte(uint32_t addr);
void spi_flash_write_byte(uint32_t addr, uint8_t wdata);
void spi_flash_write_byte(uint32_t addr, uint8_t wdata);
void spi_flash_write_word(uint32_t addr, uint32_t wdata);
void spi_flash_write_word(uint32_t addr, uint32_t wdata);
Line 170... Line 169...
  // ------------------------------------------------
  // ------------------------------------------------
  // Processor hardware initialization
  // Processor hardware initialization
  // ------------------------------------------------
  // ------------------------------------------------
 
 
  // reset system time
  // reset system time
  neorv32_mtime_set_time(0);
  MTIME_LO = 0;
 
  MTIME_HI = 0;
 
 
  // deactivate unused IO devices
  // deactivate unused IO devices
 
  neorv32_wdt_disable();
  neorv32_clic_disable();
  neorv32_clic_disable();
  neorv32_pwm_disable();
  neorv32_pwm_disable();
  neorv32_spi_disable();
  neorv32_spi_disable();
  neorv32_trng_disable();
  neorv32_trng_disable();
  neorv32_twi_disable();
  neorv32_twi_disable();
  neorv32_wdt_disable();
 
 
 
  // get clock speed (in Hz)
  // get clock speed (in Hz)
  uint32_t clock_speed = neorv32_cpu_csr_read(CSR_MCLOCK);
  uint32_t clock_speed = SYSINFO_CLK;
 
 
  // init SPI for 8-bit, clock-mode 0, MSB-first, no interrupt
  // init SPI for 8-bit, clock-mode 0, MSB-first, no interrupt
  if (clock_speed < 40000000) {
  if (clock_speed < 40000000) {
    neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0, 0, 0);
    neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0, 0, 0);
  }
  }
Line 216... Line 216...
  // ------------------------------------------------
  // ------------------------------------------------
  // Show bootloader intro and system info
  // Show bootloader intro and system info
  // ------------------------------------------------
  // ------------------------------------------------
  neorv32_uart_print("\n\n\n\n<< NEORV32 Bootloader >>\n\n"
  neorv32_uart_print("\n\n\n\n<< NEORV32 Bootloader >>\n\n"
                     "BLDV: "__DATE__"\nHWV:  ");
                     "BLDV: "__DATE__"\nHWV:  ");
  print_proc_version();
  neorv32_rte_print_hw_version();
  neorv32_uart_print("\nCLK:  ");
  neorv32_uart_print("\nCLK:  ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MCLOCK));
  print_hex_word(SYSINFO_CLK);
  neorv32_uart_print(" Hz\nMHID: ");
  neorv32_uart_print(" Hz\nUSER: ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MHARTID));
  print_hex_word(SYSINFO_USER_CODE);
  neorv32_uart_print("\nMISA: ");
  neorv32_uart_print("\nMISA: ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MISA));
  print_hex_word(neorv32_cpu_csr_read(CSR_MISA));
  neorv32_uart_print("\nCONF: ");
  neorv32_uart_print("\nCONF: ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MFEATURES));
  print_hex_word(SYSINFO_FEATURES);
  neorv32_uart_print("\nIMEM: ");
  neorv32_uart_print("\nIMEM: ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MISPACESIZE));
  print_hex_word(SYSINFO_ISPACE_SIZE);
  neorv32_uart_print(" bytes @ ");
  neorv32_uart_print(" bytes @ ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MISPACEBASE));
  print_hex_word(SYSINFO_ISPACE_BASE);
  neorv32_uart_print("\nDMEM: ");
  neorv32_uart_print("\nDMEM: ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MDSPACESIZE));
  print_hex_word(SYSINFO_DSPACE_SIZE);
  neorv32_uart_print(" bytes @ ");
  neorv32_uart_print(" bytes @ ");
  print_hex_word(neorv32_cpu_csr_read(CSR_MDSPACEBASE));
  print_hex_word(SYSINFO_DSPACE_BASE);
 
 
 
 
  // ------------------------------------------------
  // ------------------------------------------------
  // Auto boot sequence
  // Auto boot sequence
  // ------------------------------------------------
  // ------------------------------------------------
Line 264... Line 264...
    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 == 'r') { // restart bootloader
      break;
      neorv32_cpu_dint(); // disable global interrupts
 
      // jump to beginning of boot ROM
 
      asm volatile ("li t0, %[input_i]; jr t0" :  : [input_i] "i" (BOOTLOADER_BASE_ADDRESS));
 
      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 289... Line 292...
    else { // unknown command
    else { // unknown command
      neorv32_uart_print("Invalid CMD");
      neorv32_uart_print("Invalid CMD");
    }
    }
  }
  }
 
 
  return 0; // bootloader will restart when returning
  return 0; // bootloader should never return
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Print help menu.
 * Print help menu.
Line 331... Line 334...
  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 ("csrrw zero, mcycle,    zero"); // will also clear 'cycle'
 
  asm volatile ("csrrw zero, mcycleh,   zero"); // will also clear 'cycleh'
 
  asm volatile ("csrrw zero, minstret,  zero"); // will also clear 'instret'
 
  asm volatile ("csrrw zero, minstreth, zero"); // will also clear 'instreth'
 
 
  // start app at instruction space base address
  // start app at instruction space base address
  while (1) {
  while (1) {
    register uint32_t app_base = neorv32_cpu_csr_read(CSR_MISPACEBASE);
    register uint32_t app_base = SYSINFO_ISPACE_BASE;
    asm volatile ("jalr zero, %0" : : "r" (app_base));
    asm volatile ("jalr zero, %0" : : "r" (app_base));
  }
  }
}
}
 
 
 
 
Line 347... Line 356...
 **************************************************************************/
 **************************************************************************/
void __attribute__((__interrupt__)) mtime_irq_handler(void) {
void __attribute__((__interrupt__)) mtime_irq_handler(void) {
 
 
  // make sure this was caused by MTIME IRQ
  // 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);
  if (cause != 0x80000007) { // raw exception code for MTI
  if (cause != EXCCODE_MTI) { // raw exception code for MTI
    neorv32_uart_print("\n\nEXCEPTION: ");
    neorv32_uart_print("\n\nEXCEPTION: ");
    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 359... Line 368...
  }
  }
  else {
  else {
    // 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() + (neorv32_cpu_csr_read(CSR_MCLOCK)/4));
    neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
Line 372... Line 381...
 * @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) {
 
 
  // is instruction memory (actually, the IMEM) read-only?
  // is instruction memory (actually, the IMEM) read-only?
  if (neorv32_cpu_csr_read(CSR_MFEATURES) & (1 << CPU_MFEATURES_MEM_INT_IMEM_ROM)) {
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) {
    system_error(ERROR_ROM);
    system_error(ERROR_ROM);
  }
  }
 
 
  // flash image base address
  // flash image base address
  uint32_t addr = SPI_FLASH_BOOT_ADR;
  uint32_t addr = SPI_FLASH_BOOT_ADR;
Line 403... Line 412...
  // image size and checksum
  // image size and checksum
  uint32_t size  = get_exe_word(src, addr + EXE_OFFSET_SIZE); // size in bytes
  uint32_t size  = get_exe_word(src, addr + EXE_OFFSET_SIZE); // size in bytes
  uint32_t check = get_exe_word(src, addr + EXE_OFFSET_CHECKSUM); // complement sum checksum
  uint32_t check = get_exe_word(src, addr + EXE_OFFSET_CHECKSUM); // complement sum checksum
 
 
  // executable too large?
  // executable too large?
  uint32_t imem_size = neorv32_cpu_csr_read(CSR_MISPACESIZE);
  uint32_t imem_size = SYSINFO_ISPACE_SIZE;
  if (size > imem_size) {
  if (size > imem_size) {
    system_error(ERROR_SIZE);
    system_error(ERROR_SIZE);
  }
  }
 
 
  // transfer program data
  // transfer program data
  uint32_t *pnt = (uint32_t*)neorv32_cpu_csr_read(CSR_MISPACEBASE);
  uint32_t *pnt = (uint32_t*)SYSINFO_ISPACE_BASE;
  uint32_t checksum = 0;
  uint32_t checksum = 0;
  uint32_t d = 0, i = 0;
  uint32_t d = 0, i = 0;
  addr = addr + EXE_OFFSET_DATA;
  addr = addr + EXE_OFFSET_DATA;
  while (i < (size/4)) { // in words
  while (i < (size/4)) { // in words
    d = get_exe_word(src, addr);
    d = get_exe_word(src, addr);
Line 495... Line 504...
  // write size
  // write size
  spi_flash_write_word(addr + EXE_OFFSET_SIZE, size);
  spi_flash_write_word(addr + EXE_OFFSET_SIZE, size);
 
 
  // store data from instruction memory and update checksum
  // store data from instruction memory and update checksum
  uint32_t checksum = 0;
  uint32_t checksum = 0;
  uint32_t *pnt = (uint32_t*)neorv32_cpu_csr_read(CSR_MISPACEBASE);
  uint32_t *pnt = (uint32_t*)SYSINFO_ISPACE_BASE;
  addr = addr + EXE_OFFSET_DATA;
  addr = addr + EXE_OFFSET_DATA;
  uint32_t i = 0;
  uint32_t i = 0;
  while (i < (size/4)) { // in words
  while (i < (size/4)) { // in words
    uint32_t d = (uint32_t)*pnt++;
    uint32_t d = (uint32_t)*pnt++;
    checksum += d;
    checksum += d;
Line 586... Line 595...
    neorv32_uart_putc(hex_symbols[index]);
    neorv32_uart_putc(hex_symbols[index]);
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
 
 * Print processor version. Deciaml format: "Dd.Dd.Dd.Dd".
 
 **************************************************************************/
 
void print_proc_version(void) {
 
 
 
  uint32_t i;
 
  char tmp, cnt;
 
  uint32_t version = neorv32_cpu_csr_read(CSR_MIMPID);
 
 
 
  for (i=0; i<4; i++) {
 
 
 
    tmp = (char)(version >> (24 - 8*i));
 
 
 
    // serial division
 
    cnt = 0;
 
    while (tmp >= 10) {
 
      tmp = tmp - 10;
 
      cnt++;
 
    }
 
 
 
    if (cnt) {
 
      neorv32_uart_putc('0' + cnt);
 
    }
 
    neorv32_uart_putc('0' + tmp);
 
    if (i < 3) {
 
      neorv32_uart_putc('.');
 
    }
 
  }
 
}
 
 
 
 
 
 
 
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
// SPI flash functions
// SPI flash functions
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.