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

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk/sw
    from Rev 60 to Rev 61
    Reverse comparison

Rev 60 → Rev 61

/bootloader/bootloader.c
1,22 → 1,6
// #################################################################################################
// # << NEORV32 - Bootloader >> #
// # ********************************************************************************************* #
// # In order to run the bootloader on *any* CPU configuration, the bootloader should be compiled #
// # using the base ISA (rv32i/rv32e) only. #
// # ********************************************************************************************* #
// # Boot from (internal) instruction memory, UART or SPI Flash. #
// # Bootloader executables (neorv32_exe.bin) are LITTLE-ENDIAN! #
// # #
// # The bootloader uses the primary UART (UART0) for user console interface. #
// # #
// # UART configuration: 8 data bits, NO parity bit, 1 stop bit, 19200 baud (19200-8N1) #
// # Boot Flash: 8-bit SPI, 24-bit addresses (like Micron N25Q032A) @ neorv32.spi_csn_o(0) #
// # neorv32.gpio_o(0) is used as high-active status LED (can be disabled via #STATUS_LED_EN). #
// # #
// # Auto boot sequence (can be disabled via #AUTOBOOT_EN) after timeout (via #AUTOBOOT_TIMEOUT): #
// # -> Try booting from SPI flash at spi_csn_o(0). #
// # -> Permanently light up status led and stall CPU if SPI flash booting attempt fails. #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
45,7 → 29,7
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
52,7 → 36,7
/**********************************************************************//**
* @file bootloader.c
* @author Stephan Nolting
* @brief Default NEORV32 bootloader.
* @brief NEORV32 bootloader.
**************************************************************************/
 
// Libraries
61,31 → 45,73
 
 
/**********************************************************************//**
* @name User configuration
* @name Bootloader configuration (override via console to customize)
* default values are used if not explicitly customized
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE (19200)
/** Enable auto-boot sequence if != 0 */
#define AUTOBOOT_EN (1)
/** Time until the auto-boot sequence starts (in seconds) */
#define AUTOBOOT_TIMEOUT (8)
/** Set to 0 to disable bootloader status LED */
#define STATUS_LED_EN (1)
/** Set to 1 to enable SPI direct boot (disables the entire user console!) */
#define SPI_DIRECT_BOOT_EN (0)
/** Bootloader status LED at GPIO output port */
#define STATUS_LED (0)
/** SPI flash boot image base address (warning! address might wrap-around!) */
#define SPI_FLASH_BOOT_ADR (0x00800000)
/** SPI flash chip select line at spi_csn_o */
#define SPI_FLASH_CS (0)
/** Default SPI flash clock prescaler */
#define SPI_FLASH_CLK_PRSC (CLK_PRSC_8)
/** SPI flash sector size in bytes (default = 64kb) */
#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 ('#')
 
/* ---- UART interface configuration ---- */
 
/** Set to 0 to disable UART interface */
#ifndef UART_EN
#define UART_EN 1
#endif
 
/** UART BAUD rate for serial interface */
#ifndef UART_BAUD
#define UART_BAUD 19200
#endif
 
/* ---- Status LED ---- */
 
/** Set to 0 to disable bootloader status LED (heart beat) at GPIO.gpio_o(STATUS_LED_PIN) */
#ifndef STATUS_LED_EN
#define STATUS_LED_EN 1
#endif
 
/** GPIO output pin for high-active bootloader status LED (heart beat) */
#ifndef STATUS_LED_PIN
#define STATUS_LED_PIN 0
#endif
 
/* ---- Boot configuration ---- */
 
/** Set to 1 to enable automatic (after reset) boot from external SPI flash at address SPI_BOOT_BASE_ADDR */
#ifndef AUTO_BOOT_SPI_EN
#define AUTO_BOOT_SPI_EN 0
#endif
 
/** Set to 1 to enable boot via on-chip debugger (keep CPU in halt loop until OCD takes over control) */
#ifndef AUTO_BOOT_OCD_EN
#define AUTO_BOOT_OCD_EN 0
#endif
 
/** Time until the auto-boot sequence starts (in seconds); 0 = disabled */
#ifndef AUTO_BOOT_TIMEOUT
#define AUTO_BOOT_TIMEOUT 8
#endif
 
/* ---- SPI configuration ---- */
 
/** SPI flash chip select (low-active) at SPI.spi_csn_o(SPI_FLASH_CS) */
#ifndef SPI_FLASH_CS
#define SPI_FLASH_CS 0
#endif
 
/** SPI flash sector size in bytes */
#ifndef SPI_FLASH_SECTOR_SIZE
#define SPI_FLASH_SECTOR_SIZE 65536 // default = 64kB
#endif
 
/** SPI flash clock pre-scaler; see #NEORV32_TWI_CT_enum */
#ifndef SPI_FLASH_CLK_PRSC
#define SPI_FLASH_CLK_PRSC CLK_PRSC_8
#endif
 
/** SPI flash boot base address */
#ifndef SPI_BOOT_BASE_ADDR
#define SPI_BOOT_BASE_ADDR 0x08000000
#endif
/**@}*/
 
 
105,9 → 131,7
ERROR_SIGNATURE = 0, /**< 0: Wrong signature in executable */
ERROR_SIZE = 1, /**< 1: Insufficient instruction memory capacity */
ERROR_CHECKSUM = 2, /**< 2: Checksum error in executable */
ERROR_FLASH = 3, /**< 3: SPI flash access error */
ERROR_ROM = 4, /**< 4: Instruction memory is marked as read-only */
ERROR_SYSTEM = 5 /**< 5: System exception */
ERROR_FLASH = 3 /**< 3: SPI flash access error */
};
 
 
142,13 → 166,25
 
 
/**********************************************************************//**
* String output helper macros.
* Helper macros
**************************************************************************/
/**@{*/
/* Actual define-to-string helper */
/** Actual define-to-string helper */
#define xstr(a) str(a)
/* Internal helper macro */
/** Internal helper macro */
#define str(a) #a
/** Print to UART 0 */
#if (UART_EN != 0)
#define PRINT_TEXT(...) neorv32_uart0_print(__VA_ARGS__)
#define PRINT_XNUM(a) print_hex_word(a)
#define PRINT_GETC(a) neorv32_uart0_getc()
#define PRINT_PUTC(a) neorv32_uart0_putc(a)
#else
#define PRINT_TEXT(...)
#define PRINT_XNUM(a)
#define PRINT_GETC(a) 0
#define PRINT_PUTC(a)
#endif
/**@}*/
 
 
160,7 → 196,7
 
 
/**********************************************************************//**
* Only set during executable fetch (required for cpaturing STORE-BUS-TIMOUT exception).
* Only set during executable fetch (required for capturing STORE BUS-TIMOUT exception).
**************************************************************************/
volatile uint32_t getting_exe = 0;
 
167,7 → 203,6
 
// Function prototypes
void __attribute__((__interrupt__)) bootloader_trap_handler(void);
void fast_upload(int src);
void print_help(void);
void start_app(void);
void get_exe(int src);
188,121 → 223,140
 
 
/**********************************************************************//**
* Sanity check: Base ISA only!
**************************************************************************/
#if defined __riscv_atomic || defined __riscv_a || __riscv_b || __riscv_compressed || defined __riscv_c || defined __riscv_mul || defined __riscv_m
#warning In order to allow the bootloader to run on *any* CPU configuration it should be compiled using the base ISA only.
#endif
 
 
/**********************************************************************//**
* Bootloader main.
**************************************************************************/
int main(void) {
 
// check ISA
#if defined __riscv_atomic || defined __riscv_a || __riscv_b || __riscv_compressed || defined __riscv_c || defined __riscv_mul || defined __riscv_m
#warning In order to allow the bootloader to run on *ANY* CPU configuration it should be compiled using the base ISA (rv32i/e) only.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTO BOOT: OCD
// Stay in endless loop until the on-chip debugger
// takes over CPU control
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#if (AUTO_BOOT_OCD_EN != 0)
#warning Boot configuration: Boot via on-chip debugger.
while(1) {
asm volatile ("nop");
}
return 0; // should never be reached
#endif
 
exe_available = 0; // global variable for executable size; 0 means there is no exe available
getting_exe = 0; // we are not trying to get an executable yet
 
// ------------------------------------------------
// Minimal processor hardware initialization
// - all IO devices are reset and disabled by the crt0 code
// ------------------------------------------------
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTO BOOT: SPI flash
// Bootloader will directly boot and execute image from SPI flash
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#if (AUTO_BOOT_SPI_EN != 0)
#warning Boot configuration: Auto boot from external SPI flash.
 
// get clock speed (in Hz)
uint32_t clock_speed = SYSINFO_CLK;
PRINT_TEXT("\nNEORV32 bootloader\nLoading from SPI flash at ");
PRINT_XNUM((uint32_t)SPI_BOOT_BASE_ADDR);
PRINT_TEXT("...\n");
 
// init SPI for 8-bit, clock-mode 0
if (clock_speed < 40000000) {
neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0);
}
else {
neorv32_spi_setup(CLK_PRSC_128, 0, 0);
}
get_exe(EXE_STREAM_FLASH);
PRINT_TEXT("\n");
start_app();
 
#if (STATUS_LED_EN != 0)
// activate status LED, clear all others
neorv32_gpio_port_set(1 << STATUS_LED);
return 0; // bootloader should never return
#endif
 
// init UART (no parity bit, no hardware flow control)
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// Configure machine system timer interrupt for ~2Hz
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (clock_speed/4));
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTO BOOT: Default
// User UART to upload new executable and optionally store it to SPI flash
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
exe_available = 0; // global variable for executable size; 0 means there is no exe available
getting_exe = 0; // we are not trying to get an executable yet
 
 
// configure 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_eint(); // enable global interrupts
// setup SPI for 8-bit, clock-mode 0
neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0);
 
#if (STATUS_LED_EN != 0)
if (neorv32_gpio_available()) {
// activate status LED, clear all others
neorv32_gpio_port_set(1 << STATUS_LED_PIN);
}
#endif
 
// ------------------------------------------------
// 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!
// ------------------------------------------------
#if (SPI_DIRECT_BOOT_EN != 0)
#warning Compiling bootloader in 'SPI direct boot mode'. Bootloader will directly boot from SPI memory. No user UART console will be available.
#if (UART_EN != 0)
// setup UART0 (primary UART, no parity bit, no hardware flow control)
neorv32_uart0_setup(UART_BAUD, PARITY_NONE, FLOW_CONTROL_NONE);
#endif
 
neorv32_uart_print("\nNEORV32 bootloader\nAccessing SPI flash at ");
print_hex_word((uint32_t)SPI_FLASH_BOOT_ADR);
neorv32_uart_print("\n");
// Configure machine system timer interrupt for ~2Hz
if (neorv32_mtime_available()) {
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
// active timer IRQ
neorv32_cpu_csr_write(CSR_MIE, 1 << CSR_MIE_MTIE); // activate MTIME IRQ source only!
neorv32_cpu_eint(); // enable global interrupts
}
 
get_exe(EXE_STREAM_FLASH);
neorv32_uart_print("\n");
start_app();
 
return 1; // bootloader should never return
#endif
 
 
// ------------------------------------------------
// Show bootloader intro and system info
// ------------------------------------------------
neorv32_uart_print("\n\n\n\n<< NEORV32 Bootloader >>\n\n"
PRINT_TEXT("\n\n\n<< NEORV32 Bootloader >>\n\n"
"BLDV: "__DATE__"\nHWV: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MIMPID));
neorv32_uart_print("\nCLK: ");
print_hex_word(SYSINFO_CLK);
neorv32_uart_print("\nUSER: ");
print_hex_word(SYSINFO_USER_CODE);
neorv32_uart_print("\nMISA: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MISA));
neorv32_uart_print("\nZEXT: ");
print_hex_word(neorv32_cpu_csr_read(CSR_MZEXT));
neorv32_uart_print("\nPROC: ");
print_hex_word(SYSINFO_FEATURES);
neorv32_uart_print("\nIMEM: ");
print_hex_word(SYSINFO_IMEM_SIZE);
neorv32_uart_print(" bytes @ ");
print_hex_word(SYSINFO_ISPACE_BASE);
neorv32_uart_print("\nDMEM: ");
print_hex_word(SYSINFO_DMEM_SIZE);
neorv32_uart_print(" bytes @ ");
print_hex_word(SYSINFO_DSPACE_BASE);
PRINT_XNUM(neorv32_cpu_csr_read(CSR_MIMPID));
PRINT_TEXT("\nCLK: ");
PRINT_XNUM(SYSINFO_CLK);
PRINT_TEXT("\nMISA: ");
PRINT_XNUM(neorv32_cpu_csr_read(CSR_MISA));
PRINT_TEXT("\nZEXT: ");
PRINT_XNUM(neorv32_cpu_csr_read(CSR_MZEXT));
PRINT_TEXT("\nPROC: ");
PRINT_XNUM(SYSINFO_FEATURES);
PRINT_TEXT("\nIMEM: ");
PRINT_XNUM(SYSINFO_IMEM_SIZE);
PRINT_TEXT(" bytes @");
PRINT_XNUM(SYSINFO_ISPACE_BASE);
PRINT_TEXT("\nDMEM: ");
PRINT_XNUM(SYSINFO_DMEM_SIZE);
PRINT_TEXT(" bytes @");
PRINT_XNUM(SYSINFO_DSPACE_BASE);
 
 
// ------------------------------------------------
// Auto boot sequence
// ------------------------------------------------
#if (AUTOBOOT_EN != 0)
neorv32_uart_print("\n\nAutoboot in "xstr(AUTOBOOT_TIMEOUT)"s. Press key to abort.\n");
# if (AUTO_BOOT_TIMEOUT != 0)
if (neorv32_mtime_available()) {
 
uint64_t timeout_time = neorv32_mtime_get_time() + (uint64_t)(AUTOBOOT_TIMEOUT * clock_speed);
PRINT_TEXT("\n\nAutoboot in "xstr(AUTO_BOOT_TIMEOUT)"s. Press key to abort.\n");
uint64_t timeout_time = neorv32_mtime_get_time() + (uint64_t)(AUTO_BOOT_TIMEOUT * SYSINFO_CLK);
 
while (neorv32_uart_char_received() == 0) { // wait for any key to be pressed
while(1){
 
if (neorv32_mtime_get_time() >= timeout_time) { // timeout? start auto boot sequence
fast_upload(EXE_STREAM_FLASH); // try booting from flash
if (neorv32_uart0_available()) { // wait for any key to be pressed
if (neorv32_uart0_char_received()) {
break;
}
}
 
if (neorv32_mtime_get_time() >= timeout_time) { // timeout? start auto boot sequence
get_exe(EXE_STREAM_FLASH); // try booting from flash
PRINT_TEXT("\n");
start_app();
while(1);
}
 
}
PRINT_TEXT("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
neorv32_uart_print("\n\n");
PRINT_TEXT("Aborted.\n\n");
#endif
 
print_help();
313,15 → 367,12
// ------------------------------------------------
while (1) {
 
neorv32_uart_print("\nCMD:> ");
char c = neorv32_uart_getc();
neorv32_uart_putc(c); // echo
neorv32_uart_print("\n");
PRINT_TEXT("\nCMD:> ");
char c = PRINT_GETC();
PRINT_PUTC(c); // echo
PRINT_TEXT("\n");
 
if (c == FAST_UPLOAD_CMD) { // fast executable upload
fast_upload(EXE_STREAM_UART);
}
else if (c == 'r') { // restart bootloader
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
}
else if (c == 'h') { // help menu
336,11 → 387,16
else if (c == 'l') { // get executable from flash
get_exe(EXE_STREAM_FLASH);
}
else if (c == 'e') { // start application program
start_app();
else if (c == 'e') { // start application program // executable available?
if (exe_available == 0) {
PRINT_TEXT("No executable available.");
}
else {
start_app();
}
}
else { // unknown command
neorv32_uart_print("Invalid CMD");
PRINT_TEXT("Invalid CMD");
}
}
 
349,25 → 405,11
 
 
/**********************************************************************//**
* 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.
**************************************************************************/
void print_help(void) {
 
neorv32_uart_print("Available CMDs:\n"
PRINT_TEXT("Available CMDs:\n"
" h: Help\n"
" r: Restart\n"
" u: Upload\n"
382,23 → 424,13
**************************************************************************/
void start_app(void) {
 
// executable available?
if (exe_available == 0) {
neorv32_uart_print("No executable available.");
return;
}
 
// no need to shut down/reset the used peripherals
// no need to disable interrupt sources
// -> crt0 will do a clean CPU/processor reset/setup
 
// deactivate global IRQs
neorv32_cpu_dint();
 
neorv32_uart_print("Booting...\n\n");
PRINT_TEXT("Booting...\n\n");
 
// wait for UART to finish transmitting
while (neorv32_uart_tx_busy());
while (neorv32_uart0_tx_busy());
 
// start app at instruction space base address
register uint32_t app_base = SYSINFO_ISPACE_BASE;
409,35 → 441,48
 
/**********************************************************************//**
* 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 Adapt exception PC only for sync exceptions!
*
* @note 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) {
 
uint32_t cause = neorv32_cpu_csr_read(CSR_MCAUSE);
 
// make sure this was caused by MTIME IRQ
// Machine timer interrupt
if (cause == TRAP_CODE_MTI) { // raw exception code for MTI
#if (STATUS_LED_EN != 0)
// toggle status LED
neorv32_gpio_pin_toggle(STATUS_LED);
if (neorv32_gpio_available()) {
neorv32_gpio_pin_toggle(STATUS_LED_PIN); // toggle status LED
}
#endif
// set time for next IRQ
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
if (neorv32_mtime_available()) {
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
}
}
 
// Bus store access error during get_exe
else if ((cause == TRAP_CODE_S_ACCESS) && (getting_exe)) {
system_error(ERROR_SIZE); // -> seems like executable is too large
}
 
// Anything else (that was not expected); output exception notifier and try to resume
else {
// 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);
uint32_t epc = neorv32_cpu_csr_read(CSR_MEPC);
#if (UART_EN != 0)
if (neorv32_uart0_available()) {
PRINT_TEXT("\n[EXC ");
PRINT_XNUM(cause); // MCAUSE
PRINT_PUTC(' ');
PRINT_XNUM(epc); // MEPC
PRINT_PUTC(' ');
PRINT_XNUM(neorv32_cpu_csr_read(CSR_MTVAL)); // MTVAL
PRINT_TEXT("]\n");
}
// unknown error
else {
neorv32_uart_print("\n\nEXCEPTION mcause=");
print_hex_word(cause);
neorv32_uart_print(" @ pc=");
print_hex_word(neorv32_cpu_csr_read(CSR_MEPC));
system_error(ERROR_SYSTEM);
}
#endif
neorv32_cpu_csr_write(CSR_MEPC, epc + 4); // advance to next instruction
}
}
 
451,31 → 496,21
 
getting_exe = 1; // to inform trap handler we were trying to get an executable
 
// is MEM implemented and read-only?
if ((SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) &&
(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM))) {
system_error(ERROR_ROM);
}
 
// flash image base address
uint32_t addr = SPI_FLASH_BOOT_ADR;
uint32_t addr = (uint32_t)SPI_BOOT_BASE_ADDR;
 
// get image from flash?
if (src == EXE_STREAM_UART) {
neorv32_uart_print("Awaiting neorv32_exe.bin... ");
PRINT_TEXT("Awaiting neorv32_exe.bin... ");
}
else {
neorv32_uart_print("Loading... ");
PRINT_TEXT("Loading... ");
 
// check if SPI is available at all
if (neorv32_spi_available() == 0) {
// flash checks
if ((neorv32_spi_available() == 0) || // check if SPI is available at all
(spi_flash_read_1st_id() == 0x00)) { // check if flash ready (or available at all)
system_error(ERROR_FLASH);
}
 
// check if flash ready (or available at all)
if (spi_flash_read_1st_id() == 0x00) { // manufacturer ID
system_error(ERROR_FLASH);
}
}
 
// check if valid image
505,7 → 540,7
system_error(ERROR_CHECKSUM);
}
else {
neorv32_uart_print("OK");
PRINT_TEXT("OK");
exe_available = size; // store exe size
}
 
522,21 → 557,21
uint32_t size = exe_available;
 
if (size == 0) {
neorv32_uart_print("No executable available.");
PRINT_TEXT("No executable available.");
return;
}
 
uint32_t addr = SPI_FLASH_BOOT_ADR;
uint32_t addr = (uint32_t)SPI_BOOT_BASE_ADDR;
 
// info and prompt
neorv32_uart_print("Write 0x");
print_hex_word(size);
neorv32_uart_print(" bytes to SPI flash @ 0x");
print_hex_word(addr);
neorv32_uart_print("? (y/n) ");
PRINT_TEXT("Write ");
PRINT_XNUM(size);
PRINT_TEXT(" bytes to SPI flash @ ");
PRINT_XNUM(addr);
PRINT_TEXT("? (y/n) ");
 
char c = neorv32_uart_getc();
neorv32_uart_putc(c);
char c = PRINT_GETC();
PRINT_PUTC(c);
if (c != 'y') {
return;
}
546,11 → 581,11
system_error(ERROR_FLASH);
}
 
neorv32_uart_print("\nFlashing... ");
PRINT_TEXT("\nFlashing... ");
 
// clear memory before writing
uint32_t num_sectors = (size / SPI_FLASH_SECTOR_SIZE) + 1; // clear at least 1 sector
uint32_t sector = SPI_FLASH_BOOT_ADR;
uint32_t num_sectors = (size / (SPI_FLASH_SECTOR_SIZE)) + 1; // clear at least 1 sector
uint32_t sector = (uint32_t)SPI_BOOT_BASE_ADDR;
while (num_sectors--) {
spi_flash_erase_sector(sector);
sector += SPI_FLASH_SECTOR_SIZE;
577,9 → 612,9
 
// write checksum (sum complement)
checksum = (~checksum) + 1;
spi_flash_write_word(SPI_FLASH_BOOT_ADR + EXE_OFFSET_CHECKSUM, checksum);
spi_flash_write_word((uint32_t)SPI_BOOT_BASE_ADDR + EXE_OFFSET_CHECKSUM, checksum);
 
neorv32_uart_print("OK");
PRINT_TEXT("OK");
}
 
 
600,7 → 635,7
uint32_t i;
for (i=0; i<4; i++) {
if (src == EXE_STREAM_UART) {
data.uint8[i] = (uint8_t)neorv32_uart_getc();
data.uint8[i] = (uint8_t)PRINT_GETC();
}
else {
data.uint8[i] = spi_flash_read_byte(addr + i);
618,13 → 653,15
**************************************************************************/
void system_error(uint8_t err_code) {
 
neorv32_uart_print("\a\nERROR_"); // output error code with annoying bell sound
neorv32_uart_putc('0' + ((char)err_code)); // FIXME err_code should/must be below 10
PRINT_TEXT("\a\nERROR_"); // output error code with annoying bell sound
PRINT_PUTC('0' + ((char)err_code));
 
neorv32_cpu_dint(); // deactivate IRQs
if (STATUS_LED_EN == 1) {
neorv32_gpio_port_set(1 << STATUS_LED); // permanently light up status LED
#if (STATUS_LED_EN != 0)
if (neorv32_gpio_available()) {
neorv32_gpio_port_set(1 << STATUS_LED_PIN); // permanently light up status LED
}
#endif
 
while(1); // freeze
}
637,15 → 674,17
**************************************************************************/
void print_hex_word(uint32_t num) {
 
#if (UART_EN != 0)
static const char hex_symbols[16] = "0123456789abcdef";
 
neorv32_uart_print("0x");
PRINT_TEXT("0x");
 
int i;
for (i=0; i<8; i++) {
uint32_t index = (num >> (28 - 4*i)) & 0xF;
neorv32_uart_putc(hex_symbols[index]);
PRINT_PUTC(hex_symbols[index]);
}
#endif
}
 
 
/common/crt0.S
44,85 → 44,75
 
nop
 
// *********************************************************
// Clear integer register file (lower half, assume E extension)
// *********************************************************
__crt0_reg_file_clear:
//addi x0, x0, 0 // hardwired to zero
addi x1, x0, 0
addi x2, x0, 0
addi x3, x0, 0
addi x4, x0, 0
addi x5, x0, 0
addi x6, x0, 0
addi x7, x0, 0
//addi x8, x0, 0
//addi x9, x0, 0
//addi x10, x0, 0
//addi x11, x0, 0
//addi x12, x0, 0
//addi x13, x0, 0
addi x14, x0, 0
addi x15, x0, 0
 
 
// *********************************************************
// ************************************************************************************************
// Setup pointers using linker script symbols
// *********************************************************
// ************************************************************************************************
__crt0_pointer_init:
.option push
.option norelax
la sp, __crt0_stack_begin
andi sp, sp, 0xfffffffc // make sure this is aligned
addi fp, sp, 0 // frame pointer = stack pointer
la gp, __global_pointer$ // global pointer
.option pop
.option push
.option norelax
 
la sp, __crt0_stack_begin // stack pointer
la gp, __global_pointer$ // global pointer
 
// *********************************************************
// Setup CPU core CSRs (some of them DO NOT have a dedicated reset and need to be explicitly initialized)
// *********************************************************
.option pop
 
 
// ************************************************************************************************
// Setup CPU core CSRs (some of them DO NOT have a dedicated
// reset and need to be explicitly initialized)
// ************************************************************************************************
__crt0_cpu_csr_init:
 
// set address of first-level exception handler
la x10, __crt0_dummy_trap_handler
csrw mtvec, x10
csrw mepc, x10
csrw mtval, zero
csrw mcause, zero
la x10, __crt0_dummy_trap_handler // configure early trap handler
csrw mtvec, x10
csrw mepc, x10 // just to init mepc
 
// no global IRQ enable (is also done by hardware)
csrw mstatus, zero
csrw mstatus, zero // disable global IRQ
 
// absolutely no interrupts, thanks
csrw mie, zero
csrw mie, zero // absolutely no interrupts sources, thanks
 
// no access from less-privileged modes to counter CSRs
csrw mcounteren, zero
csrw mcounteren, zero // no access from less-privileged modes to counter CSRs
 
// stop all counters except for [m]cycle[h] and [m]instret[h]
li x11, ~5
csrw 0x320, x11 // mcountinhibit (literal address for lagacy toolchain compatibility)
li x11, ~5 // stop all counters except for [m]cycle[h] and [m]instret[h]
csrw 0x320, x11 // = mcountinhibit (literal address for lagacy toolchain compatibility)
 
// clear cycle counters
csrw mcycle, zero
csrw mcycleh, zero
 
// clear instruction counters
csrw minstret, zero
csrw mcycle, zero // reset cycle counters
csrw mcycleh, zero
csrw minstret, zero // reset instruction counters
csrw minstreth, zero
 
#if defined(__riscv_flen) && (__riscv_flen != 0)
// clear floating-point CSR (rounding mode & exception flags)
csrw fcsr, zero
#if defined(__riscv_flen)
csrw fcsr, zero // reset floating-point CSR
#endif
 
 
// *********************************************************
// Clear integer register file (upper half, if no E extension)
// *********************************************************
// ************************************************************************************************
// Initialize integer register file (lower half)
// ************************************************************************************************
__crt0_reg_file_clear:
//addi x0, x0, 0 // hardwired to zero
addi x1, x0, 0
//addi x2, x0, 0 // stack pointer sp
//addi x3, x0, 0 // gloabl pointer gp
addi x4, x0, 0
addi x5, x0, 0
addi x6, x0, 0
addi x7, x0, 0
//addi x8, x0, 0 // initialized within crt0
//addi x9, x0, 0 // initialized within crt0
//addi x10, x0, 0 // initialized within crt0
//addi x11, x0, 0 // initialized within crt0
//addi x12, x0, 0 // initialized within crt0
//addi x13, x0, 0 // initialized within crt0
addi x14, x0, 0
addi x15, x0, 0
 
 
// ************************************************************************************************
// Initialize integer register file (upper half, if no E extension)
// ************************************************************************************************
#ifndef __riscv_32e
// DO NOT DO THIS if compiling bootloader (to save some program space)
// do not do this if compiling bootloader (to save some program space)
#ifndef make_bootloader
addi x16, x0, 0
addi x17, x0, 0
144,14 → 134,14
#endif
 
 
// *********************************************************
// ************************************************************************************************
// Reset/deactivate IO/peripheral devices
// Devices, that are not implemented, will cause a store access fault
// which is captured but actually ignored due to the dummy handler.
// *********************************************************
// Devices, that are not implemented, will cause a store bus access fault
// which is captured (but actually ignored) by the dummy trap handler.
// ************************************************************************************************
__crt0_reset_io:
la x8, __ctr0_io_space_begin // start of processor-internal IO region
la x9, __ctr0_io_space_end // end of processor-internal IO region
la x8, __ctr0_io_space_begin // start of processor-internal IO region
la x9, __ctr0_io_space_end // end of processor-internal IO region
 
__crt0_reset_io_loop:
sw zero, 0(x8)
159,29 → 149,29
bne x8, x9, __crt0_reset_io_loop
 
 
// *********************************************************
// ************************************************************************************************
// Clear .bss section (byte-wise) using linker script symbols
// *********************************************************
// ************************************************************************************************
__crt0_clear_bss:
la x11, __crt0_bss_start
la x12, __crt0_bss_end
la x11, __crt0_bss_start
la x12, __crt0_bss_end
 
__crt0_clear_bss_loop:
bge x11, x12, __crt0_clear_bss_loop_end
bge x11, x12, __crt0_clear_bss_loop_end
sb zero, 0(x11)
addi x11, x11, 1
addi x11, x11, 1
j __crt0_clear_bss_loop
 
__crt0_clear_bss_loop_end:
 
 
// *********************************************************
// ************************************************************************************************
// Copy initialized .data section from ROM to RAM (byte-wise) using linker script symbols
// *********************************************************
// ************************************************************************************************
__crt0_copy_data:
la x11, __crt0_copy_data_src_begin // start of data area (copy source)
la x12, __crt0_copy_data_dst_begin // start of data area (copy destination)
la x13, __crt0_copy_data_dst_end // last address of destination data area
la x11, __crt0_copy_data_src_begin // start of data area (copy source)
la x12, __crt0_copy_data_dst_begin // start of data area (copy destination)
la x13, __crt0_copy_data_dst_end // last address of destination data area
 
__crt0_copy_data_loop:
bge x12, x13, __crt0_copy_data_loop_end
194,69 → 184,75
__crt0_copy_data_loop_end:
 
 
// *********************************************************
// Call main function
// *********************************************************
// ************************************************************************************************
// Setup arguments and call main function
// ************************************************************************************************
__crt0_main_entry:
addi x10, zero, 0 // a0 = argc = 0
addi x11, zero, 0 // a1 = argv = 0
jal ra, main // call actual app's main function, this "should" not return
 
// setup arguments for calling main
addi x10, zero, 0 // argc = 0
addi x11, zero, 0 // argv = 0
 
// call actual app's main function
jal ra, main
// ************************************************************************************************
// call "after main" handler (if there is any) if main really returns
// ************************************************************************************************
__crt0_main_aftermath:
csrw mscratch, a0 // copy main's return code in mscratch for debugger
 
#ifndef make_bootloader // after_main handler not supported for bootloader
.weak __neorv32_crt0_after_main
la ra, __neorv32_crt0_after_main
beqz ra, __crt0_main_aftermath_end // check if an aftermath handler has been specified
jalr ra // execute handler, main's return code in a0
#endif
 
// *********************************************************
// Go to endless sleep mode if main returns
// *********************************************************
__crt0_this_is_the_end:
csrrci zero, mstatus, 8 // mstatus: disable global IRQs (MIE)
__crt0_this_is_the_end_my_friend:
wfi
j __crt0_this_is_the_end_my_friend
 
// ************************************************************************************************
// go to endless sleep mode
// ************************************************************************************************
__crt0_main_aftermath_end:
csrci mstatus, 8 // mstatus: disable global IRQs (mstatus.mie)
__crt0_main_aftermath_end_loop:
wfi // try to go to sleep mode
j __crt0_main_aftermath_end_loop // endless loop
 
// *********************************************************
// dummy trap handler (for exceptions & IRQs)
// tries to move on to next instruction
// *********************************************************
.global __crt0_dummy_trap_handler
 
// ************************************************************************************************
// dummy trap handler (for exceptions & IRQs during very early boot stage)
// does nothing but tries to move on to next instruction
// ************************************************************************************************
.balign 4
__crt0_dummy_trap_handler:
 
addi sp, sp, -8
sw x8, 0(sp)
sw x9, 4(sp)
addi sp, sp, -8
sw x8, 0(sp)
sw x9, 4(sp)
 
csrr x8, mcause
blt x8, zero, __crt0_dummy_trap_handler_irq // skip mepc modification if interrupt
csrr x8, mcause
blt x8, zero, __crt0_dummy_trap_handler_irq // skip mepc modification if interrupt
 
csrr x8, mepc
csrr x8, mepc
 
// is compressed instruction?
__crt0_dummy_trap_handler_exc_c_check:
lh x9, 0(x8) // get compressed instruction or lower 16 bits of uncompressed instruction that caused exception
andi x9, x9, 3 // mask: isolate lowest 2 opcode bits (= 11 for uncompressed instructions)
__crt0_dummy_trap_handler_exc_c_check: // is compressed instruction?
lh x9, 0(x8) // get compressed instruction or lower 16 bits of uncompressed instruction that caused exception
andi x9, x9, 3 // mask: isolate lowest 2 opcode bits (= 11 for uncompressed instructions)
 
addi x8, x8, +2 // only this for compressed instructions
csrw mepc, x8 // set return address when compressed instruction
addi x8, x8, +2 // only this for compressed instructions
csrw mepc, x8 // set return address when compressed instruction
 
addi x8, zero, 3
bne x8, x9, __crt0_dummy_trap_handler_irq // jump if compressed instruction
// is uncompressed instruction
__crt0_dummy_trap_handler_exc_uncrompressed:
csrr x8, mepc
addi x8, x8, +2 // add another 2 (making +4) for uncompressed instructions
addi x8, zero, 3
bne x8, x9, __crt0_dummy_trap_handler_irq // jump if compressed instruction
 
__crt0_dummy_trap_handler_exc_uncrompressed: // is uncompressed instruction!
csrr x8, mepc
addi x8, x8, +2 // add another 2 (making +4) for uncompressed instructions
csrw mepc, x8
 
__crt0_dummy_trap_handler_irq:
lw x8, 0(sp)
lw x9, 4(sp)
addi sp, sp, +8
 
lw x8, 0(sp)
lw x9, 4(sp)
addi sp, sp, +8
 
mret
 
.cfi_endproc
/common/neorv32.ld
36,7 → 36,7
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
notice and this notice are preserved. */
 
/* modified for the NEORV32 processor by Stephan Nolting */
 
46,20 → 46,25
ENTRY(_start)
SEARCH_DIR("/opt/riscv/riscv32-unknown-elf/lib"); SEARCH_DIR("=/opt/riscv/riscv64-unknown-linux-gnu/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
 
/* ************************************************************************* */
/* NEORV32 memory configuration. */
/* Make sure this is sync with your processor/memory hardware configuration! */
/* ************************************************************************* */
/* "rom" : instruction memory (IMEM) / bootloader ROM */
/* "ram" : data memory (DMEM) */
/* "iodev" : peripheral/IO devices (not used here; passed to crt0) */
/* ************************************************************************* */
/* ************************************************************************** */
/* NEORV32 memory section configuration. */
/* ************************************************************************** */
/* "ram" : data memory (int/ext DMEM) - make sure this is sync with the HW! */
/* "rom" : instruction memory (int/ext IMEM or bootloader ROM) */
/* "iodev" : peripheral/IO devices */
/* ************************************************************************** */
MEMORY
{
/* "rom" section: first value of ORIGIN/LENGTH => bootloader ROM; second value of ORIGIN/LENGTH => instruction memory */
/* section base addresses and sizes have to be a multiple of 4-bytes */
/* ram section: first value of LENGTH => data memory used by bootloader (fixed!); second value of LENGTH => *physical* size of data memory */
/* adapt the right-most value to match the *total physical data memory size* of your setup */
 
rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 4*1024 : 16*1024
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 8*1024
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024
 
/* rom and iodev sections should NOT be modified by the user at all! */
/* rom section: first value of ORIGIN/LENGTH => bootloader ROM; second value of ORIGIN/LENGTH => maximum *logical* size of instruction memory */
 
rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 32K : 2048M
iodev (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512
 
}
67,9 → 72,6
 
SECTIONS
{
/* stack pointer init: last 32-bit entry in data memory */
__crt0_stack_begin = (ORIGIN(ram) + LENGTH(ram)) - 4;
 
/* start section on WORD boundary */
. = ALIGN(4);
 
291,7 → 293,8
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
 
 
/* Provide further symbols for neorv32 crt0 */
/* Provide symbols for neorv32 crt0 start-up code */
PROVIDE(__crt0_stack_begin = (ORIGIN(ram) + LENGTH(ram)) - 4);
PROVIDE(__crt0_bss_start = __bss_start);
PROVIDE(__crt0_bss_end = __BSS_END__);
PROVIDE(__crt0_copy_data_src_begin = __etext + SIZEOF(.rodata));
/example/blink_led/main.c
79,7 → 79,7
// check if GPIO unit is implemented at all
if (neorv32_gpio_available() == 0) {
neorv32_uart_print("Error! No GPIO unit synthesized!\n");
return 0; // nope, no GPIO unit synthesized
return 1; // nope, no GPIO unit synthesized
}
 
// capture all exceptions and give debug info via UART
86,9 → 86,6
// this is not required, but keeps us safe
neorv32_rte_setup();
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
 
// say hello
neorv32_uart_print("Blinking LED demo program\n");
 
/example/demo_xirq/main.c
0,0 → 1,196
// #################################################################################################
// # << NEORV32 - External Interrupt Controller (XIRQ) Demo Program >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file demo_xirq/main.c
* @author Stephan Nolting
* @brief External interrupt controller (XIRQ) demo program.
**************************************************************************/
 
#include <neorv32.h>
 
 
/**********************************************************************//**
* @name User configuration
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
/**@}*/
 
// prototypes
void xirq_handler_ch0(void);
void xirq_handler_ch1(void);
void xirq_handler_ch2(void);
void xirq_handler_ch3(void);
 
 
/**********************************************************************//**
* Main function
*
* @note This program requires the WDT and the UART to be synthesized.
*
* @return 0 if execution was successful
**************************************************************************/
int main() {
 
// initialize the neorv32 runtime environment
// this will take care of handling all CPU traps (interrupts and exceptions)
neorv32_rte_setup();
 
// setup UART0 at default baud rate, no parity bits, ho hw flow control
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check if XIRQ unit is implemented at all
if (neorv32_xirq_available() == 0) {
neorv32_uart0_printf("XIRQ not synthesized!\n");
return 1;
}
 
 
// intro
neorv32_uart0_printf("External interrupt controller (XIRQ) demo program\n\n");
 
int err_cnt = 0;
 
 
// initialize XIRQ controller
// this will disable all XIRQ channels and will also clear any pending external interrupts
// (details: this will register the XIRQ's second-level interrupt handler in the NEORV32 RTE)
err_cnt = neorv32_xirq_setup();
 
// check if setup went fine
if (err_cnt) {
neorv32_uart0_printf("Error during XIRQ setup!\n");
return 1;
}
 
 
// install handler functions for XIRQ channel 0,1,2,3. note that these functions are "normal" functions!
// (details: these are "third-level" interrupt handler)
err_cnt = 0;
err_cnt += neorv32_xirq_install(0, xirq_handler_ch0); // handler function for channel 0
err_cnt += neorv32_xirq_install(1, xirq_handler_ch1); // handler function for channel 1
err_cnt += neorv32_xirq_install(2, xirq_handler_ch2); // handler function for channel 2
err_cnt += neorv32_xirq_install(3, xirq_handler_ch3); // handler function for channel 3
 
// check if installation went fine
if (err_cnt) {
neorv32_uart0_printf("Error during XIRQ install!\n");
return 1;
}
 
 
// allow XIRQ to trigger CPU interrupt
neorv32_xirq_global_enable();
 
 
// enable global interrupts
neorv32_cpu_eint();
 
 
// now we are ready to got!
// the code below assumes the XIRQ inputs are connected to the processor's GPIO output port
// so we can trigger the IRQs from software; if you have connected the XIRQs to buttons you
// can remove the code below (note the trigger configuration using the XIRQ generics!)
{
// trigger XIRQs 3:0 at once
// assumes xirq_i <= gpio.output(31:0)
 
// due to the prioritization this will execute
// -> xirq_handler_ch0
// -> xirq_handler_ch1
// -> xirq_handler_ch2
// -> xirq_handler_ch3
neorv32_gpio_port_set(0xF); // set output pins 3:0 -> trigger XIRQ 3:0
neorv32_gpio_port_set(0x0);
}
 
 
// wait for interrupts
while(1);
 
 
// just as an example: to disable certain XIRQ interrupt channels, we can
// uninstall the according handler. this will also clear a pending interrupt for that channel
neorv32_xirq_uninstall(0); // disable XIRQ channel 0 and remove associated handler
neorv32_xirq_uninstall(1); // disable XIRQ channel 1 and remove associated handler
neorv32_xirq_uninstall(2); // disable XIRQ channel 2 and remove associated handler
neorv32_xirq_uninstall(3); // disable XIRQ channel 3 and remove associated handler
 
 
return 0;
}
 
 
/**********************************************************************//**
* XIRQ handler channel 0.
*
* @warning This function has to be of type "void xyz(void)" and must not use any interrupt attributes!
**************************************************************************/
void xirq_handler_ch0(void) {
 
neorv32_uart0_printf("XIRQ interrupt from channel %i\n", 0);
}
 
/**********************************************************************//**
* XIRQ handler channel 1.
*
* @warning This function has to be of type "void xyz(void)" and must not use any interrupt attributes!
**************************************************************************/
void xirq_handler_ch1(void) {
 
neorv32_uart0_printf("XIRQ interrupt from channel %i\n", 1);
}
 
/**********************************************************************//**
* XIRQ handler channel 2.
*
* @warning This function has to be of type "void xyz(void)" and must not use any interrupt attributes!
**************************************************************************/
void xirq_handler_ch2(void) {
 
neorv32_uart0_printf("XIRQ interrupt from channel %i\n", 2);
}
 
/**********************************************************************//**
* XIRQ handler channel 3.
*
* @warning This function has to be of type "void xyz(void)" and must not use any interrupt attributes!
**************************************************************************/
void xirq_handler_ch3(void) {
 
neorv32_uart0_printf("XIRQ interrupt from channel %i\n", 3);
}
/example/demo_xirq/makefile
0,0 → 1,338
#################################################################################################
# << NEORV32 - Application Makefile >> #
# ********************************************************************************************* #
# Make sure to add the RISC-V GCC compiler's bin folder to your PATH environment variable. #
# ********************************************************************************************* #
# BSD 3-Clause License #
# #
# Copyright (c) 2021, Stephan Nolting. All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without modification, are #
# permitted provided that the following conditions are met: #
# #
# 1. Redistributions of source code must retain the above copyright notice, this list of #
# conditions and the following disclaimer. #
# #
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
# conditions and the following disclaimer in the documentation and/or other materials #
# provided with the distribution. #
# #
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
# endorse or promote products derived from this software without specific prior written #
# permission. #
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
# OF THE POSSIBILITY OF SUCH DAMAGE. #
# ********************************************************************************************* #
# The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
#################################################################################################
 
 
# *****************************************************************************
# USER CONFIGURATION
# *****************************************************************************
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S)
 
# User's application include folders (don't forget the '-I' before each entry)
APP_INC ?= -I .
# User's application include folders - for assembly files only (don't forget the '-I' before each entry)
ASM_INC ?= -I .
 
# Optimization
EFFORT ?= -Os
 
# Compiler toolchain
RISCV_TOOLCHAIN ?= riscv32-unknown-elf
 
# CPU architecture and ABI
MARCH ?= -march=rv32i
MABI ?= -mabi=ilp32
 
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
 
# Serial port for executable upload via bootloer
COM_PORT ?= /dev/ttyUSB0
 
# Relative or absolute path to the NEORV32 home folder
NEORV32_HOME ?= ../../..
# *****************************************************************************
 
 
 
# -----------------------------------------------------------------------------
# NEORV32 framework
# -----------------------------------------------------------------------------
# Path to NEORV32 linker script and startup file
NEORV32_COM_PATH = $(NEORV32_HOME)/sw/common
# Path to main NEORV32 library include files
NEORV32_INC_PATH = $(NEORV32_HOME)/sw/lib/include
# Path to main NEORV32 library source files
NEORV32_SRC_PATH = $(NEORV32_HOME)/sw/lib/source
# Path to NEORV32 executable generator
NEORV32_EXG_PATH = $(NEORV32_HOME)/sw/image_gen
# Path to NEORV32 core rtl folder
NEORV32_RTL_PATH = $(NEORV32_HOME)/rtl/core
# Marker file to check for NEORV32 home folder
NEORV32_HOME_MARKER = $(NEORV32_INC_PATH)/neorv32.h
 
# Core libraries (peripheral and CPU drivers)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
# Application start-up code
CORE_SRC += $(NEORV32_COM_PATH)/crt0.S
 
# Linker script
LD_SCRIPT = $(NEORV32_COM_PATH)/neorv32.ld
 
# Main output files
APP_EXE = neorv32_exe.bin
APP_ASM = main.asm
APP_IMG = neorv32_application_image.vhd
BOOT_IMG = neorv32_bootloader_image.vhd
 
 
# -----------------------------------------------------------------------------
# Sources and objects
# -----------------------------------------------------------------------------
# Define all sources
SRC = $(APP_SRC)
SRC += $(CORE_SRC)
 
# Define all object files
OBJ = $(SRC:%=%.o)
 
 
# -----------------------------------------------------------------------------
# Tools and flags
# -----------------------------------------------------------------------------
# Compiler tools
CC = $(RISCV_TOOLCHAIN)-gcc
OBJDUMP = $(RISCV_TOOLCHAIN)-objdump
OBJCOPY = $(RISCV_TOOLCHAIN)-objcopy
SIZE = $(RISCV_TOOLCHAIN)-size
 
# Host native compiler
CC_X86 = g++ -Wall -O -g
 
# NEORV32 executable image generator
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen
 
# Compiler & linker flags
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv
CC_OPTS += -Wl,--gc-sections -lm -lc -lgcc -lc
# This accelerates instruction fetch after branches when C extension is enabled (irrelevant when C extension is disabled)
CC_OPTS += -falign-functions=4 -falign-labels=4 -falign-loops=4 -falign-jumps=4
CC_OPTS += $(USER_FLAGS)
 
 
# -----------------------------------------------------------------------------
# Application output definitions
# -----------------------------------------------------------------------------
.PHONY: check info help elf_info clean clean_all bootloader
.DEFAULT_GOAL := help
 
# 'compile' is still here for compatibility
exe: $(APP_ASM) $(APP_EXE)
compile: $(APP_ASM) $(APP_EXE)
install: $(APP_ASM) $(APP_IMG)
all: $(APP_ASM) $(APP_EXE) $(APP_IMG)
 
# Check if making bootloader
# Use different base address and legth for instruction memory/"rom" (BOOTMEM instead of IMEM)
# Also define "make_bootloader" for crt0.S
target bootloader: CC_OPTS += -Wl,--defsym=make_bootloader=1 -Dmake_bootloader
 
 
# -----------------------------------------------------------------------------
# Image generator targets
# -----------------------------------------------------------------------------
# install/compile tools
$(IMAGE_GEN): $(NEORV32_EXG_PATH)/image_gen.cpp
@echo Compiling $(IMAGE_GEN)
@$(CC_X86) $< -o $(IMAGE_GEN)
 
 
# -----------------------------------------------------------------------------
# General targets: Assemble, compile, link, dump
# -----------------------------------------------------------------------------
# Compile app *.s sources (assembly)
%.s.o: %.s
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@
 
# Compile app *.S sources (assembly + C pre-processor)
%.S.o: %.S
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@
 
# Compile app *.c sources
%.c.o: %.c
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@
 
# Compile app *.cpp sources
%.cpp.o: %.cpp
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@
 
# Link object files and show memory utilization
main.elf: $(OBJ)
@$(CC) $(CC_OPTS) -T $(LD_SCRIPT) $(OBJ) -o $@ -lm
@echo "Memory utilization:"
@$(SIZE) main.elf
 
# Assembly listing file (for debugging)
$(APP_ASM): main.elf
@$(OBJDUMP) -d -S -z $< > $@
 
# Generate final executable from .text + .rodata + .data (in THIS order!)
main.bin: main.elf $(APP_ASM)
@$(OBJCOPY) -I elf32-little $< -j .text -O binary text.bin
@$(OBJCOPY) -I elf32-little $< -j .rodata -O binary rodata.bin
@$(OBJCOPY) -I elf32-little $< -j .data -O binary data.bin
@cat text.bin rodata.bin data.bin > $@
@rm -f text.bin rodata.bin data.bin
 
 
# -----------------------------------------------------------------------------
# Application targets: Generate binary executable, install (as VHDL file)
# -----------------------------------------------------------------------------
# Generate NEORV32 executable image for upload via bootloader
$(APP_EXE): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_bin $< $@ $(shell basename $(CURDIR))
@echo "Executable ($(APP_EXE)) size in bytes:"
@wc -c < $(APP_EXE)
 
# Generate NEORV32 executable VHDL boot image
$(APP_IMG): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_img $< $@ $(shell basename $(CURDIR))
@echo "Installing application image to $(NEORV32_RTL_PATH)/$(APP_IMG)"
@cp $(APP_IMG) $(NEORV32_RTL_PATH)/.
 
 
# -----------------------------------------------------------------------------
# Bootloader targets
# -----------------------------------------------------------------------------
# Create and install bootloader VHDL init image
$(BOOT_IMG): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -bld_img $< $(BOOT_IMG) $(shell basename $(CURDIR))
@echo "Installing bootloader image to $(NEORV32_RTL_PATH)/$(BOOT_IMG)"
@cp $(BOOT_IMG) $(NEORV32_RTL_PATH)/.
 
# Just an alias that
bootloader: $(BOOT_IMG)
 
 
# -----------------------------------------------------------------------------
# Check toolchain
# -----------------------------------------------------------------------------
check: $(IMAGE_GEN)
@echo "---------------- Check: NEORV32_HOME folder ----------------"
ifneq ($(shell [ -e $(NEORV32_HOME_MARKER) ] && echo 1 || echo 0 ), 1)
$(error NEORV32_HOME folder not found!)
endif
@echo "NEORV32_HOME: $(NEORV32_HOME)"
@echo "---------------- Check: $(CC) ----------------"
@$(CC) -v
@echo "---------------- Check: $(OBJDUMP) ----------------"
@$(OBJDUMP) -V
@echo "---------------- Check: $(OBJCOPY) ----------------"
@$(OBJCOPY) -V
@echo "---------------- Check: $(SIZE) ----------------"
@$(SIZE) -V
@echo "---------------- Check: NEORV32 image_gen ----------------"
@$(IMAGE_GEN) -help
@echo "---------------- Check: Native GCC ----------------"
@$(CC_X86) -v
@echo
@echo "Toolchain check OK"
 
 
# -----------------------------------------------------------------------------
# Upload executable via serial port to bootloader
# -----------------------------------------------------------------------------
upload: $(APP_EXE)
@sh $(NEORV32_EXG_PATH)/uart_upload.sh $(COM_PORT) $(APP_EXE)
 
 
# -----------------------------------------------------------------------------
# Show configuration
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "ASM include folder(s): $(ASM_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "---------------- Info: Objects ----------------"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
@echo "---------------- Info: Toolchain ----------------"
@echo "Toolchain: $(RISCV_TOLLCHAIN)"
@echo "CC: $(CC)"
@echo "OBJDUMP: $(OBJDUMP)"
@echo "OBJCOPY: $(OBJCOPY)"
@echo "SIZE: $(SIZE)"
@echo "---------------- Info: Compiler Libraries ----------------"
@echo "LIBGCC:"
@$(CC) -print-libgcc-file-name
@echo "SEARCH-DIRS:"
@$(CC) -print-search-dirs
@echo "---------------- Info: Flags ----------------"
@echo "USER_FLAGS: $(USER_FLAGS)"
@echo "CC_OPTS: $(CC_OPTS)"
@echo "---------------- Info: Host Native GCC Flags ----------------"
@echo "CC_X86: $(CC_X86)"
 
 
# -----------------------------------------------------------------------------
# Show final ELF details (just for debugging)
# -----------------------------------------------------------------------------
elf_info: main.elf
@$(OBJDUMP) -x main.elf
 
 
# -----------------------------------------------------------------------------
# Help
# -----------------------------------------------------------------------------
help:
@echo "<<< NEORV32 Application Makefile >>>"
@echo "Make sure to add the bin folder of RISC-V GCC to your PATH variable."
@echo "Targets:"
@echo " help - show this text"
@echo " check - check toolchain"
@echo " info - show makefile/toolchain configuration"
@echo " exe - compile and generate <neorv32_exe.bin> executable for upload via bootloader"
@echo " install - compile, generate and install VHDL IMEM boot image (for application)"
@echo " all - compile and generate <neorv32_exe.bin> executable for upload via bootloader and generate and install VHDL IMEM boot image (for application)"
@echo " clean - clean up project"
@echo " clean_all - clean up project, core libraries and image generator"
@echo " bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)"
@echo " upload - upload <neorv32_exe.bin> executable via serial port <COM_PORT> to bootloader"
 
 
# -----------------------------------------------------------------------------
# Clean up
# -----------------------------------------------------------------------------
clean:
@rm -f *.elf *.o *.bin *.out *.asm *.vhd
 
clean_all: clean
@rm -f $(OBJ) $(IMAGE_GEN)
/example/hex_viewer/main.c
210,7 → 210,7
char terminal_buffer[16];
uint32_t mem_address, rdata, wdata, status;
 
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) {
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
 
// enter memory address
neorv32_uart_printf("Enter memory address (8 hex chars): 0x");
/example/processor_check/check.sh
33,6 → 33,7
clean_all \
USER_FLAGS+=-DRUN_CHECK \
USER_FLAGS+=-DUART0_SIM_MODE \
USER_FLAGS+=-DUART1_SIM_MODE \
MARCH=-march=rv32imac \
info \
all
/example/processor_check/main.c
58,9 → 58,30
/**@}*/
 
 
/**********************************************************************//**
* @name UART print macros
**************************************************************************/
/**@{*/
//** for simulation only! */
#ifdef SUPPRESS_OPTIONAL_UART_PRINT
//** print standard output to UART0 */
#define PRINT_STANDARD(...)
//** print critical output to UART1 */
#define PRINT_CRITICAL(...) neorv32_uart1_printf(__VA_ARGS__)
#else
//** print standard output to UART0 */
#define PRINT_STANDARD(...) neorv32_uart0_printf(__VA_ARGS__)
//** print critical output to UART0 */
#define PRINT_CRITICAL(...) neorv32_uart0_printf(__VA_ARGS__)
#endif
/**@}*/
 
 
// Prototypes
void sim_irq_trigger(uint32_t sel);
void global_trap_handler(void);
void xirq_trap_handler0(void);
void xirq_trap_handler1(void);
void test_ok(void);
void test_fail(void);
 
71,10 → 92,12
int cnt_ok = 0;
/// Global counter for total number of tests
int cnt_test = 0;
/// Global numbe rof available HPMs
/// Global number of available HPMs
uint32_t num_hpm_cnts_global = 0;
/// XIRQ trap handler acknowledge
uint32_t xirq_trap_handler_ack = 0;
 
/// Variable to test atomic accessess
/// Variable to test atomic accesses
uint32_t atomic_access_addr;
 
 
82,6 → 105,8
* High-level CPU/processor test program.
*
* @note Applications has to be compiler with <USER_FLAGS+=-DRUN_CPUTEST>
* @warning This test is intended for simulation only.
* @warning This test requires all optional extensions/modules to be enabled.
*
* @return 0 if execution was successful
**************************************************************************/
88,31 → 113,27
int main() {
 
register uint32_t tmp_a, tmp_b;
volatile uint32_t dummy_dst __attribute__((unused));
uint8_t id;
uint32_t is_simulation = 0;
 
 
// init UART at default baud rate, no parity bits, no hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
// init UARTs at default baud rate, no parity bits, no hw flow control
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
UART1_CT = UART0_CT; // copy configuration to initialize UART1
 
#ifdef SUPPRESS_OPTIONAL_UART_PRINT
neorv32_uart0_disable(); // do not generate any UART0 output
#endif
 
// Disable processor_check compilation by default
#ifndef RUN_CHECK
#warning processor_check HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.
 
// inform the user if you are actually executing this
neorv32_uart_printf("ERROR! processor_check has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
PRINT_CRITICAL("ERROR! processor_check has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
 
return 1;
#endif
 
// check if this is a simulation (using primary UART0)
if (UART0_CT & (1 << UART_CT_SIM_MODE)) {
is_simulation = 1;
}
else {
is_simulation = 0;
}
 
// ----------------------------------------------
// setup RTE
124,8 → 145,8
 
 
// intro
neorv32_uart_printf("\n<< PROCESSOR CHECK >>\n");
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n");
PRINT_STANDARD("\n<< PROCESSOR CHECK >>\n");
PRINT_STANDARD("build: "__DATE__" "__TIME__"\n");
 
 
// reset performance counter
156,7 → 177,7
 
// configure RTE
// -----------------------------------------------
neorv32_uart_printf("\n\nConfiguring NEORV32 RTE... ");
PRINT_STANDARD("\n\nConfiguring NEORV32 RTE... ");
 
int install_err = 0;
// initialize ALL provided trap handler (overriding the default debug handlers)
165,18 → 186,18
}
 
if (install_err) {
neorv32_uart_printf("RTE install error (%i)!\n", install_err);
PRINT_CRITICAL("RTE install error (%i)!\n", install_err);
return 1;
}
 
// enable interrupt sources
neorv32_cpu_irq_enable(CSR_MIE_MSIE); // machine software interrupt
neorv32_cpu_irq_enable(CSR_MIE_MTIE); // machine timer interrupt
neorv32_cpu_irq_enable(CSR_MIE_MEIE); // machine external interrupt
neorv32_cpu_irq_enable(CSR_MIE_MSIE); // machine software interrupt
neorv32_cpu_irq_enable(CSR_MIE_MTIE); // machine timer interrupt
neorv32_cpu_irq_enable(CSR_MIE_MEIE); // machine external interrupt
// enable FAST IRQ sources only where actually needed
 
// test intro
neorv32_uart_printf("\nStarting tests...\n\n");
PRINT_STANDARD("\nStarting tests...\n\n");
 
// enable global interrupts
neorv32_cpu_eint();
186,7 → 207,7
// Test standard RISC-V performance counter [m]cycle[h]
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] [m]instret[h] counter: ", cnt_test);
PRINT_STANDARD("[%i] [m]cycle[h] counter: ", cnt_test);
 
cnt_test++;
 
193,12 → 214,14
// make sure counter is enabled
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY));
 
// get current cycle counter LOW
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLE);
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLE) - tmp_a;
// prepare overflow
neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
 
// make sure cycle counter has incremented and there was no exception during access
if ((tmp_a > 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
// get current cycle counter HIGH
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLEH);
 
// make sure cycle counter high has incremented and there was no exception during access
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
test_ok();
}
else {
210,7 → 233,7
// Test standard RISC-V performance counter [m]instret[h]
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] [m]cycle[h] counter: ", cnt_test);
PRINT_STANDARD("[%i] [m]instret[h] counter: ", cnt_test);
 
cnt_test++;
 
217,19 → 240,15
// make sure counter is enabled
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_IR));
 
// get instruction counter LOW
tmp_a = neorv32_cpu_csr_read(CSR_INSTRET);
tmp_a = neorv32_cpu_csr_read(CSR_INSTRET) - tmp_a;
// prepare overflow
neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
 
// make sure instruction counter has incremented and there was no exception during access
if ((tmp_a > 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
if (tmp_a > 1) {
neorv32_uart_printf("INSTRET_diff > 1 (%u)!", tmp_a);
test_fail();
}
else {
test_ok();
}
// get instruction counter HIGH
tmp_a = neorv32_cpu_csr_read(CSR_INSTRETH);
 
// make sure instruction counter high has incremented and there was no exception during access
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
test_ok();
}
else {
test_fail();
240,7 → 259,7
// Test mcountinhibt: inhibit auto-inc of [m]cycle
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] mcountinhibt.cy CSR: ", cnt_test);
PRINT_STANDARD("[%i] mcountinhibt.cy CSR: ", cnt_test);
 
cnt_test++;
 
276,10 → 295,10
// Test mcounteren: do not allow cycle[h] access from user-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] mcounteren.cy CSR: ", cnt_test);
PRINT_STANDARD("[%i] mcounteren.cy CSR: ", cnt_test);
 
// skip if U-mode is not implemented
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U_EXT)) {
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) {
cnt_test++;
 
// do not allow user-level code to access cycle[h] CSRs
308,7 → 327,7
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
}
 
 
322,7 → 341,7
// Test performance counter: setup as many events and counter as feasible
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Initializing HPMs: ", cnt_test);
PRINT_STANDARD("[%i] Configuring HPM events: ", cnt_test);
 
num_hpm_cnts_global = neorv32_cpu_hpm_get_counters();
 
353,114 → 372,87
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
}
 
 
//// ----------------------------------------------------------
//// Bus timeout latency estimation
//// out of order :P
//// ----------------------------------------------------------
//neorv32_cpu_csr_write(CSR_MCAUSE, 0);
//neorv32_uart_printf("[%i] Estimating bus time-out latency: ", cnt_test);
//cnt_test++;
//
//// start timing
//neorv32_cpu_csr_write(CSR_MCYCLE, 0);
//
//// make sure there was a timeout
//if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) {
// neorv32_uart_printf("~%u cycles ", trap_timestamp32-175); // remove trap handler overhead - empiric value ;)
// test_ok();
//}
//else {
// test_fail();
//}
 
 
// ----------------------------------------------------------
// External memory interface test
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] External memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
PRINT_STANDARD("[%i] External memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
 
if (is_simulation) { // check if this is a simulation
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)) {
cnt_test++;
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)) {
cnt_test++;
 
// create test program in RAM
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
0x3407D073, // csrwi mscratch, 15
0x00008067 // ret (32-bit)
};
// create test program in RAM
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
0x3407D073, // csrwi mscratch, 15
0x00008067 // ret (32-bit)
};
 
// copy to external memory
if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) {
test_fail();
}
else {
// copy to external memory
if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) {
test_fail();
}
else {
 
// execute program
tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a));
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { // make sure there was no exception
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15) { // make sure the program was executed in the right way
test_ok();
}
else {
test_fail();
}
// execute program
tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a));
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { // make sure there was no exception
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15) { // make sure the program was executed in the right way
test_ok();
}
else {
test_fail();
}
}
else {
test_fail();
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
}
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
PRINT_STANDARD("skipped (n.a.)\n");
}
 
 
//// ----------------------------------------------------------
//// Test FENCE.I instruction (instruction buffer / i-cache clear & reload)
//// ----------------------------------------------------------
//neorv32_cpu_csr_write(CSR_MCAUSE, 0);
//neorv32_uart_printf("[%i] FENCE.I: ", cnt_test);
//
//// check if implemented
//if (neorv32_cpu_csr_read(CSR_MZEXT) & (1 << CSR_MZEXT_ZIFENCEI)) {
// cnt_test++;
//
// asm volatile ("fence.i");
//
// // make sure there was no exception (and that the cpu did not crash...)
// if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// test_ok();
// }
// else {
// test_fail();
// }
//}
//else {
// neorv32_uart_printf("skipped (not implemented)\n");
//}
// ----------------------------------------------------------
// Test FENCE.I instruction (instruction buffer / i-cache clear & reload)
// if Zifencei is not implemented FENCE.I should execute as NOP
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FENCE.I: ", cnt_test);
 
cnt_test++;
 
asm volatile ("fence.i");
 
// make sure there was no exception (and that the cpu did not crash...)
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
test_ok();
}
else {
test_fail();
}
 
 
// ----------------------------------------------------------
// Illegal CSR access (CSR not implemented)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Illegal CSR (0xfff) access: ", cnt_test);
PRINT_STANDARD("[%i] Non-existent CSR access: ", cnt_test);
 
cnt_test++;
 
neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented
tmp_a = neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented
 
if (tmp_a != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
test_ok();
}
473,7 → 465,7
// Write-access to read-only CSR
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Read-only CSR (time) write access: ", cnt_test);
PRINT_STANDARD("[%i] Read-only CSR write access: ", cnt_test);
 
cnt_test++;
 
491,7 → 483,7
// No "real" CSR write access (because rs1 = r0)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Read-only CSR (time) no-write (rs1=0) access: ", cnt_test);
PRINT_STANDARD("[%i] Read-only CSR 'no-write' (rs1=0) access: ", cnt_test);
 
cnt_test++;
 
511,37 → 503,33
// Test pending interrupt
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Pending IRQ test (from MTIME): ", cnt_test);
PRINT_STANDARD("[%i] Pending IRQ test (MTIME): ", cnt_test);
 
if (neorv32_mtime_available()) {
cnt_test++;
cnt_test++;
 
// disable global interrupts
neorv32_cpu_dint();
// disable global interrupts
neorv32_cpu_dint();
 
// force MTIME IRQ
neorv32_mtime_set_timecmp(0);
// prepare MTIME IRQ
neorv32_mtime_set_time(0x00000000FFFFFFF8ULL); // prepare overflow
neorv32_mtime_set_timecmp(0x0000000100000000ULL); // IRQ on overflow
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
// no more mtime interrupts
neorv32_mtime_set_timecmp(-1);
// no more mtime interrupts
neorv32_mtime_set_timecmp(-1);
 
// re-enable global interrupts
neorv32_cpu_eint();
// re-enable global interrupts
neorv32_cpu_eint();
 
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
test_ok();
}
else {
test_fail();
}
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
test_ok();
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
test_fail();
}
 
 
549,10 → 537,10
// Unaligned instruction address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] I_ALIGN (instr. alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] I_ALIGN (instr. alignment) EXC: ", cnt_test);
 
// skip if C-mode is implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C_EXT)) == 0) {
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) == 0) {
 
cnt_test++;
 
560,16 → 548,16
((void (*)(void))ADDR_UNALIGNED)();
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_MISALIGNED) {
neorv32_uart_printf("ok\n");
PRINT_STANDARD("ok\n");
cnt_ok++;
}
else {
neorv32_uart_printf("fail\n");
PRINT_STANDARD("fail\n");
cnt_fail++;
}
}
else {
neorv32_uart_printf("skipped (n.a. with C-ext)\n");
PRINT_STANDARD("skipped (n.a. with C-ext)\n");
}
 
 
577,7 → 565,7
// Instruction access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] I_ACC (instr. bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] I_ACC (instr. bus access) EXC: ", cnt_test);
cnt_test++;
 
// call unreachable aligned address
595,7 → 583,7
// Illegal instruction
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
PRINT_STANDARD("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
 
cnt_test++;
 
621,10 → 609,10
// Illegal compressed instruction
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] CI_ILLEG (illegal compr. instr.) EXC: ", cnt_test);
PRINT_STANDARD("[%i] CI_ILLEG (illegal compr. instr.) EXC: ", cnt_test);
 
// skip if C-mode is not implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C_EXT)) != 0) {
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) != 0) {
 
cnt_test++;
 
645,7 → 633,7
}
}
else {
neorv32_uart_printf("skipped (n.a. with C-ext)\n");
PRINT_STANDARD("skipped (n.a. with C-ext)\n");
}
 
 
653,7 → 641,7
// Breakpoint instruction
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] BREAK (break instr.) EXC: ", cnt_test);
PRINT_STANDARD("[%i] BREAK (break instr.) EXC: ", cnt_test);
cnt_test++;
 
asm volatile("EBREAK");
670,11 → 658,11
// Unaligned load address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] L_ALIGN (load addr alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] L_ALIGN (load addr alignment) EXC: ", cnt_test);
cnt_test++;
 
// load from unaligned address
asm volatile ("lw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED));
neorv32_cpu_load_unsigned_word(ADDR_UNALIGNED);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) {
test_ok();
688,11 → 676,11
// Load access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] L_ACC (load bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] L_ACC (load bus access) EXC: ", cnt_test);
cnt_test++;
 
// load from unreachable aligned address
dummy_dst = neorv32_cpu_load_unsigned_word(ADDR_UNREACHABLE);
neorv32_cpu_load_unsigned_word(ADDR_UNREACHABLE);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) {
test_ok();
706,7 → 694,7
// Unaligned store address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] S_ALIGN (store addr alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] S_ALIGN (store addr alignment) EXC: ", cnt_test);
cnt_test++;
 
// store to unaligned address
724,7 → 712,7
// Store access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] S_ACC (store bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] S_ACC (store bus access) EXC: ", cnt_test);
cnt_test++;
 
// store to unreachable aligned address
742,7 → 730,7
// Environment call from M-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] ENVCALL (ecall instr.) from M-mode EXC: ", cnt_test);
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from M-mode EXC: ", cnt_test);
cnt_test++;
 
asm volatile("ECALL");
759,10 → 747,10
// Environment call from U-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] ENVCALL (ecall instr.) from U-mode EXC: ", cnt_test);
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from U-mode EXC: ", cnt_test);
 
// skip if U-mode is not implemented
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U_EXT)) {
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) {
 
cnt_test++;
 
781,7 → 769,7
 
}
else {
neorv32_uart_printf("skipped (n.a. without U-ext)\n");
PRINT_STANDARD("skipped (n.a. without U-ext)\n");
}
 
 
789,66 → 777,56
// Machine timer interrupt (MTIME)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] MTI (via MTIME): ", cnt_test);
PRINT_STANDARD("[%i] MTI (via MTIME): ", cnt_test);
 
if (neorv32_mtime_available()) {
cnt_test++;
cnt_test++;
 
// configure MTIME IRQ (and check overflow form low owrd to high word)
neorv32_mtime_set_timecmp(-1);
neorv32_mtime_set_time(0);
// configure MTIME IRQ (and check overflow form low owrd to high word)
neorv32_mtime_set_timecmp(-1);
neorv32_mtime_set_time(0);
 
neorv32_cpu_csr_write(CSR_MIP, 0); // clear all pending IRQs
neorv32_cpu_csr_write(CSR_MIP, 0); // clear all pending IRQs
 
neorv32_mtime_set_timecmp(0x0000000100000000ULL);
neorv32_mtime_set_time( 0x00000000FFFFFFFEULL);
neorv32_mtime_set_timecmp(0x0000000100000000ULL);
neorv32_mtime_set_time( 0x00000000FFFFFFFEULL);
 
// wait some time for the IRQ to trigger and arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to trigger and arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
test_ok();
}
else {
test_fail();
}
 
// no more mtime interrupts
neorv32_mtime_set_timecmp(-1);
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
test_ok();
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
test_fail();
}
 
// no more mtime interrupts
neorv32_mtime_set_timecmp(-1);
 
 
// ----------------------------------------------------------
// Machine software interrupt (MSI) via testbench
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] MSI (via testbench): ", cnt_test);
PRINT_STANDARD("[%i] MSI (via testbench): ", cnt_test);
 
if (is_simulation) { // check if this is a simulation
cnt_test++;
cnt_test++;
 
// trigger IRQ
sim_irq_trigger(1 << CSR_MIE_MSIE);
// trigger IRQ
sim_irq_trigger(1 << CSR_MIE_MSIE);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MSI) {
test_ok();
}
else {
test_fail();
}
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MSI) {
test_ok();
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
test_fail();
}
 
 
856,27 → 834,22
// Machine external interrupt (MEI) via testbench
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] MEI (via testbench): ", cnt_test);
PRINT_STANDARD("[%i] MEI (via testbench): ", cnt_test);
 
if (is_simulation) { // check if this is a simulation
cnt_test++;
cnt_test++;
 
// trigger IRQ
sim_irq_trigger(1 << CSR_MIE_MEIE);
// trigger IRQ
sim_irq_trigger(1 << CSR_MIE_MEIE);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MEI) {
test_ok();
}
else {
test_fail();
}
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MEI) {
test_ok();
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
test_fail();
}
 
 
884,27 → 857,22
// Non-maskable interrupt (NMI) via testbench
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] NMI (via testbench): ", cnt_test);
PRINT_STANDARD("[%i] NMI (via testbench): ", cnt_test);
 
if (is_simulation) { // check if this is a simulation
cnt_test++;
cnt_test++;
 
// trigger IRQ
sim_irq_trigger(1 << 0);
// trigger IRQ
sim_irq_trigger(1 << 0);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_NMI) {
test_ok();
}
else {
test_fail();
}
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_NMI) {
test_ok();
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
test_fail();
}
 
 
911,10 → 879,10
// ----------------------------------------------------------
// Fast interrupt channel 0 (WDT)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ0 test (via WDT): ", cnt_test);
if (neorv32_wdt_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ0 test (via WDT): ", cnt_test);
 
if (neorv32_wdt_available()) {
cnt_test++;
 
// enable fast interrupt
942,25 → 910,22
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 1 (CFS)
// ----------------------------------------------------------
neorv32_uart_printf("[%i] FIRQ1 test (via CFS): ", cnt_test);
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("[%i] FIRQ1 test (via CFS): ", cnt_test);
PRINT_STANDARD("skipped (n.a.)\n");
 
 
// ----------------------------------------------------------
// Fast interrupt channel 2 (UART0.RX)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ2 test (via UART0.RX): ", cnt_test);
if (neorv32_uart1_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ2 test (via UART0.RX): ", cnt_test);
 
if (is_simulation) { // check if this is a simulation
cnt_test++;
 
// enable fast interrupt
967,26 → 932,27
neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E);
 
// wait for UART0 to finish transmitting
while(neorv32_uart_tx_busy());
while(neorv32_uart0_tx_busy());
 
// backup current UART0 configuration
tmp_a = UART0_CT;
 
// disable UART0 sim_mode if it is enabled
// make sure UART is enabled
UART0_CT |= (1 << UART_CT_EN);
// make sure sim mode is disabled
UART0_CT &= ~(1 << UART_CT_SIM_MODE);
 
// trigger UART0 RX IRQ
// the default test bench connects UART0.TXD_O to UART0_RXD_I
UART0_DATA = 0; // we need to access the raw HW here, since >UART0_SIM_MODE< might be active
neorv32_uart0_putc(0);
 
// wait for UART0 to finish transmitting
while(neorv32_uart_tx_busy());
while(neorv32_uart0_tx_busy());
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
// re-enable UART0 sim_mode if it was enabled
// restore original configuration
UART0_CT = tmp_a;
 
// disable fast interrupt
999,74 → 965,77
test_fail();
}
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 3 (UART0.TX)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ3 test (via UART0.TX): ", cnt_test);
if (neorv32_uart0_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ3 test (via UART0.TX): ", cnt_test);
 
cnt_test++;
cnt_test++;
 
// UART0 TX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
// UART0 TX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
 
// wait for UART0 to finish transmitting
while(neorv32_uart_tx_busy());
// wait for UART0 to finish transmitting
while(neorv32_uart0_tx_busy());
 
// backup current UART0 configuration
tmp_a = UART0_CT;
// backup current UART0 configuration
tmp_a = UART0_CT;
 
// disable UART0 sim_mode if it is enabled
UART0_CT &= ~(1 << UART_CT_SIM_MODE);
// make sure UART is enabled
UART0_CT |= (1 << UART_CT_EN);
// make sure sim mode is disabled
UART0_CT &= ~(1 << UART_CT_SIM_MODE);
 
// trigger UART0 TX IRQ
UART0_DATA = 0; // we need to access the raw HW here, since >UART0_SIM_MODE< might be active
// trigger UART0 TX IRQ
neorv32_uart0_putc(0);
 
// wait for UART to finish transmitting
while(neorv32_uart_tx_busy());
// wait for UART to finish transmitting
while(neorv32_uart0_tx_busy());
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
// re-enable UART sim_mode if it was enabled
UART0_CT = tmp_a;
// restore original configuration
UART0_CT = tmp_a;
 
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
test_ok();
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
test_ok();
}
else {
test_fail();
}
}
else {
test_fail();
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 4 (UART1.RX)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ4 test (via UART1.RX): ", cnt_test);
if (neorv32_uart1_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ4 test (via UART1.RX): ", cnt_test);
 
if ((neorv32_uart1_available()) && (is_simulation)) { // UART1 available and we are in a simulation
cnt_test++;
 
// UART1 RX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
 
// initialize UART1
UART1_CT = 0;
tmp_a = UART0_CT; // copy configuration from UART0
tmp_a &= ~(1 << UART_CT_SIM_MODE); // make sure sim_mode is disabled
UART1_CT = tmp_a;
// backup current UART1 configuration
tmp_a = UART1_CT;
 
// make sure UART is enabled
UART1_CT |= (1 << UART_CT_EN);
// make sure sim mode is disabled
UART1_CT &= ~(1 << UART_CT_SIM_MODE);
 
// trigger UART1 RX IRQ
UART1_DATA = 0;
neorv32_uart1_putc(0);
 
// wait for UART1 to finish transmitting
while(neorv32_uart1_tx_busy());
1075,8 → 1044,8
asm volatile("nop");
asm volatile("nop");
 
// disable UART1
UART1_CT = 0;
// restore original configuration
UART1_CT = tmp_a;
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
1088,31 → 1057,30
test_fail();
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 5 (UART1.TX)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ5 test (via UART1.TX): ", cnt_test);
if (neorv32_uart1_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ5 test (via UART1.TX): ", cnt_test);
 
if (neorv32_uart1_available()) {
cnt_test++;
 
// UART1 RX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
 
// initialize UART1
UART1_CT = 0;
tmp_a = UART0_CT; // copy configuration from UART0
tmp_a &= ~(1 << UART_CT_SIM_MODE); // make sure sim_mode is disabled
UART1_CT = tmp_a;
// backup current UART1 configuration
tmp_a = UART1_CT;
 
// make sure UART is enabled
UART1_CT |= (1 << UART_CT_EN);
// make sure sim mode is disabled
UART1_CT &= ~(1 << UART_CT_SIM_MODE);
 
// trigger UART1 TX IRQ
UART1_DATA = 0;
neorv32_uart1_putc(0);
 
// wait for UART1 to finish transmitting
while(neorv32_uart1_tx_busy());
1121,8 → 1089,8
asm volatile("nop");
asm volatile("nop");
 
// disable UART1
UART1_CT = 0;
// restore original configuration
UART1_CT = tmp_a;
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
1134,18 → 1102,15
test_fail();
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 6 (SPI)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ6 test (via SPI): ", cnt_test);
if (neorv32_spi_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ6 test (via SPI): ", cnt_test);
 
if (neorv32_spi_available()) {
cnt_test++;
 
// enable fast interrupt
1175,18 → 1140,15
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ6E);
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 7 (TWI)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ7 test (via TWI): ", cnt_test);
if (neorv32_twi_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ7 test (via TWI): ", cnt_test);
 
if (neorv32_twi_available()) {
cnt_test++;
 
// configure TWI, fastest clock, no peripheral clock stretching
1214,157 → 1176,143
neorv32_twi_disable();
neorv32_cpu_irq_disable(CSR_MIE_FIRQ7E);
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 8 (GPIO)
// Fast interrupt channel 8 (XIRQ)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ8 test (via GPIO): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ8 test (via XIRQ): ", cnt_test);
if (neorv32_xirq_available()) {
 
if (is_simulation) { // check if this is a simulation
if (neorv32_gpio_available()) {
cnt_test++;
cnt_test++;
 
// clear output port
neorv32_gpio_port_set(0);
int xirq_err_cnt = 0;
xirq_trap_handler_ack = 0;
 
neorv32_cpu_irq_enable(CSR_MIE_FIRQ8E);
xirq_err_cnt += neorv32_xirq_setup(); // initialize XIRQ
xirq_err_cnt += neorv32_xirq_install(0, xirq_trap_handler0); // install XIRQ IRQ handler channel 0
xirq_err_cnt += neorv32_xirq_install(1, xirq_trap_handler1); // install XIRQ IRQ handler channel 1
 
// configure GPIO.in(31) for pin-change IRQ
neorv32_gpio_pin_change_config(0x80000000);
neorv32_xirq_global_enable(); // enable XIRQ FIRQ
 
// trigger pin-change IRQ by setting GPIO.out(31)
// the testbench connects GPIO.out => GPIO.in
neorv32_gpio_pin_set(31);
// trigger XIRQ channel 1 and 0
neorv32_gpio_port_set(3);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
// wait for IRQs to arrive CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_8) {
test_ok();
}
else {
test_fail();
}
 
// disable GPIO pin-change IRQ
neorv32_gpio_pin_change_config(0);
 
// clear output port
neorv32_gpio_port_set(0);
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_8) && // FIRQ8 IRQ
(xirq_err_cnt == 0) && // no errors during XIRQ configuration
(xirq_trap_handler_ack == 4)) { // XIRQ channel handler 0 executed before handler 1
test_ok();
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
test_fail();
}
 
neorv32_xirq_global_disable();
XIRQ_IER = 0;
XIRQ_IPR = -1;
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 9 (reserved)
// Fast interrupt channel 9 (NEOLED)
// ----------------------------------------------------------
neorv32_uart_printf("[%i] FIRQ9: ", cnt_test);
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("[%i] FIRQ9 (NEOLED): skipped\n", cnt_test);
 
 
// ----------------------------------------------------------
// Fast interrupt channel 10..15 (SoC fast IRQ 0..5)
// Fast interrupt channel 10 & 11 (SLINK)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ10..15 (SoC fast IRQ 0..5; via testbench): ", cnt_test);
if (neorv32_slink_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test);
 
if (is_simulation) { // check if this is a simulation
 
cnt_test++;
 
// enable SOC FIRQs
for (id=CSR_MIE_FIRQ10E; id<=CSR_MIE_FIRQ15E; id++) {
neorv32_cpu_irq_enable(id);
// enable SLINK
neorv32_slink_enable();
 
// enable SLINK FIRQs
neorv32_cpu_irq_enable(CSR_MIE_FIRQ10E);
neorv32_cpu_irq_enable(CSR_MIE_FIRQ11E);
 
tmp_a = 0; // error counter
 
// send single data word via link 0
if (neorv32_slink_tx0_nonblocking(0xA1B2C3D4)) {
tmp_a++; // sending failed
}
 
// trigger all SoC Fast interrupts at once
neorv32_cpu_dint(); // do not fire yet!
sim_irq_trigger((1 << CSR_MIE_FIRQ10E) | (1 << CSR_MIE_FIRQ11E) | (1 << CSR_MIE_FIRQ12E) | (1 << CSR_MIE_FIRQ13E) | (1 << CSR_MIE_FIRQ14E) | (1 << CSR_MIE_FIRQ15E));
// get single data word from link 0
uint32_t slink_rx_data;
if (neorv32_slink_rx0_nonblocking(&slink_rx_data)) {
tmp_a++; // receiving failed
}
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
 
// make sure all SoC FIRQs have been triggered
tmp_a = (1 << CSR_MIP_FIRQ10P) | (1 << CSR_MIP_FIRQ11P) | (1 << CSR_MIP_FIRQ12P) | (1 << CSR_MIP_FIRQ13P) | (1 << CSR_MIP_FIRQ14P) | (1 << CSR_MIP_FIRQ15P);
 
if (neorv32_cpu_csr_read(CSR_MIP) == tmp_a) {
neorv32_cpu_eint(); // allow IRQs to fire again
asm volatile ("nop");
asm volatile ("nop"); // irq should kick in HERE
 
tmp_a = neorv32_cpu_csr_read(CSR_MCAUSE);
if ((tmp_a >= TRAP_CODE_FIRQ_8) && (tmp_a <= TRAP_CODE_FIRQ_15)) {
test_ok();
}
else {
test_fail();
}
tmp_b = neorv32_cpu_csr_read(CSR_MCAUSE);
if (((tmp_b == TRAP_CODE_FIRQ_10) || (tmp_b == TRAP_CODE_FIRQ_11)) && // right trap code
(tmp_a == 0) && // local error counter = 0
(slink_rx_data == 0xA1B2C3D4)) { // correct data read-back
test_ok();
}
else {
test_fail();
}
 
// disable SOC FIRQs
for (id=CSR_MIE_FIRQ10E; id<=CSR_MIE_FIRQ15E; id++) {
neorv32_cpu_irq_disable(id);
}
// shutdown SLINK
neorv32_slink_disable();
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
}
 
neorv32_cpu_eint(); // re-enable IRQs globally
 
//// ----------------------------------------------------------
//// Fast interrupt channel 12..15 (reserved)
//// ----------------------------------------------------------
//PRINT_STANDARD("[%i] FIRQ12..15: ", cnt_test);
//PRINT_STANDARD("skipped (n.a.)\n");
 
 
// ----------------------------------------------------------
// Test WFI ("sleep") instructions, wakeup via MTIME
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] WFI (sleep instruction) test (wake-up via MTIME): ", cnt_test);
PRINT_STANDARD("[%i] WFI (sleep instruction) test (wake-up via MTIME): ", cnt_test);
 
if (neorv32_mtime_available()) {
cnt_test++;
cnt_test++;
 
// program wake-up timer
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 1000);
// program wake-up timer
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 1000);
 
// put CPU into sleep mode
asm volatile ("wfi");
// put CPU into sleep mode
asm volatile ("wfi");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) {
test_fail();
}
else {
test_ok();
}
 
// no more mtime interrupts
neorv32_mtime_set_timecmp(-1);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) {
test_fail();
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
test_ok();
}
 
// no more mtime interrupts
neorv32_mtime_set_timecmp(-1);
 
 
// ----------------------------------------------------------
// Test invalid CSR access in user mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test);
PRINT_STANDARD("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test);
 
// skip if U-mode is not implemented
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U_EXT)) {
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_U)) {
 
cnt_test++;
 
1375,13 → 1323,12
tmp_a = neorv32_cpu_csr_read(CSR_MISA);
}
 
if (tmp_a != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
if (tmp_a == 0) { // make sure user-level code CANNOT read machine-level CSR content!
test_ok();
}
else {
test_fail();
}
test_ok();
}
else {
test_fail();
1389,7 → 1336,7
 
}
else {
neorv32_uart_printf("skipped (n.a. without U-ext)\n");
PRINT_STANDARD("skipped (n.a. without U-ext)\n");
}
 
 
1397,7 → 1344,7
// Test RTE debug trap handler
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] RTE (runtime env.) debug trap handler: ", cnt_test);
PRINT_STANDARD("[%i] RTE debug trap handler: ", cnt_test);
 
cnt_test++;
 
1407,13 → 1354,13
// trigger illegal instruction exception
neorv32_cpu_csr_read(0xfff); // CSR not available
 
neorv32_uart_printf(" ");
PRINT_STANDARD(" ");
if (neorv32_cpu_csr_read(CSR_MCAUSE) != 0) {
test_ok();
}
else {
test_fail();
neorv32_uart_printf("answer: 0x%x", neorv32_cpu_csr_read(CSR_MCAUSE));
PRINT_STANDARD("answer: 0x%x", neorv32_cpu_csr_read(CSR_MCAUSE));
}
 
// restore original handler
1423,7 → 1370,7
// ----------------------------------------------------------
// Test physical memory protection
// ----------------------------------------------------------
neorv32_uart_printf("[%i] PMP - Physical memory protection: ", cnt_test);
PRINT_STANDARD("[%i] PMP - Physical memory protection: ", cnt_test);
 
// check if PMP is implemented
if (neorv32_cpu_pmp_get_num_regions() != 0) {
1433,14 → 1380,14
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
cnt_test++;
 
// find out mininmal region size (granulartiy)
// find out minimal region size (granularity)
tmp_b = neorv32_cpu_pmp_get_granularity();
 
tmp_a = SYSINFO_DSPACE_BASE; // base address of protected region
neorv32_uart_printf("Creating protected page (NAPOT, [!X,!W,R], %u bytes) @ 0x%x: ", tmp_b, tmp_a);
PRINT_STANDARD("Creating protected page (NAPOT, [!X,!W,!R], %u bytes) @ 0x%x: ", tmp_b, tmp_a);
 
// configure
int pmp_return = neorv32_cpu_pmp_configure_region(0, tmp_a, tmp_b, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions
int pmp_return = neorv32_cpu_pmp_configure_region(0, tmp_a, tmp_b, 0b00011000); // NAPOT, NO read permission, NO write permission, and NO execute permissions
 
if ((pmp_return == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
test_ok();
1451,7 → 1398,7
 
 
// ------ EXECUTE: should fail ------
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] execute: ", cnt_test);
PRINT_STANDARD("[%i] PMP: U-mode execute: ", cnt_test);
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
1462,13 → 1409,13
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// switch back to machine mode (if not allready)
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_fail();
}
else {
// switch back to machine mode (if not allready)
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_ok();
1475,8 → 1422,8
}
 
 
// ------ LOAD: should work ------
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] read: ", cnt_test);
// ------ LOAD: should fail ------
PRINT_STANDARD("[%i] PMP: U-mode read: ", cnt_test);
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
1483,17 → 1430,21
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
asm volatile ("lw zero, 0(%[input_i])" : : [input_i] "r" (tmp_a)); // load access -> should work
tmp_b = neorv32_cpu_load_unsigned_word(tmp_a); // load access -> should fail
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// switch back to machine mode (if not allready)
if (tmp_b != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) {
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_ok();
}
else {
// switch back to machine mode (if not allready)
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_fail();
1501,7 → 1452,7
 
 
// ------ STORE: should fail ------
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] write: ", cnt_test);
PRINT_STANDARD("[%i] PMP: U-mode write: ", cnt_test);
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
1508,17 → 1459,17
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
asm volatile ("sw zero, 0(%[input_i])" : : [input_i] "r" (tmp_a)); // store access -> should fail
neorv32_cpu_store_unsigned_word(tmp_a, 0); // store access -> should fail
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) {
// switch back to machine mode (if not allready)
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_ok();
}
else {
// switch back to machine mode (if not allready)
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_fail();
1526,7 → 1477,7
 
 
// ------ Lock test - pmpcfg0.0 / pmpaddr0 ------
neorv32_uart_printf("[%i] PMP: Entry [mode=off] lock: ", cnt_test);
PRINT_STANDARD("[%i] PMP: Entry [mode=off] lock: ", cnt_test);
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
1548,7 → 1499,7
 
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
}
 
 
1556,11 → 1507,11
// Test atomic LR/SC operation - should succeed
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Atomic access (LR+SC succeeding access): ", cnt_test);
PRINT_STANDARD("[%i] Atomic access (LR+SC succeeding access): ", cnt_test);
 
#ifdef __riscv_atomic
// skip if A-mode is not implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) {
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
 
cnt_test++;
 
1582,10 → 1533,10
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
}
#else
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
#endif
 
 
1593,11 → 1544,11
// Test atomic LR/SC operation - should fail
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Atomic access (LR+SC failing access 1): ", cnt_test);
PRINT_STANDARD("[%i] Atomic access (LR+SC failing access 1): ", cnt_test);
 
#ifdef __riscv_atomic
// skip if A-mode is not implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) {
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
 
cnt_test++;
 
1618,10 → 1569,10
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
}
#else
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
#endif
 
 
1629,11 → 1580,11
// Test atomic LR/SC operation - should fail
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Atomic access (LR+SC failing access 2): ", cnt_test);
PRINT_STANDARD("[%i] Atomic access (LR+SC failing access 2): ", cnt_test);
 
#ifdef __riscv_atomic
// skip if A-mode is not implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) {
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
 
cnt_test++;
 
1654,10 → 1605,10
}
}
else {
neorv32_uart_printf("skipped (on real HW)\n");
PRINT_STANDARD("skipped (on real HW)\n");
}
#else
neorv32_uart_printf("skipped (not implemented)\n");
PRINT_STANDARD("skipped (n.a.)\n");
#endif
 
 
1665,39 → 1616,38
// HPM reports
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, -1); // stop all counters
neorv32_uart_printf("\n\n-- HPM reports LOW (%u HPMs available) --\n", num_hpm_cnts_global);
neorv32_uart_printf("#IR - Total number of instr.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); // = "HPM_0"
//neorv32_uart_printf("#TM - Current system time: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_TIME)); // = "HPM_1"
neorv32_uart_printf("#CY - Total number of clk cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE)); // = "HPM_2"
neorv32_uart_printf("#03 - Retired compr. instr.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3));
neorv32_uart_printf("#04 - I-fetch wait cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4));
neorv32_uart_printf("#05 - I-issue wait cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5));
neorv32_uart_printf("#06 - Multi-cyc. ALU wait cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6));
neorv32_uart_printf("#07 - Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7));
neorv32_uart_printf("#08 - Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8));
neorv32_uart_printf("#09 - Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9));
neorv32_uart_printf("#10 - Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10));
neorv32_uart_printf("#11 - Cond. branches (total): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11));
neorv32_uart_printf("#12 - Cond. branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12));
neorv32_uart_printf("#13 - Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13));
neorv32_uart_printf("#14 - Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14));
PRINT_STANDARD("\n\n-- HPM reports LOW (%u HPMs available) --\n", num_hpm_cnts_global);
PRINT_STANDARD("#IR - Instr.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); // = "HPM_0"
//PRINT_STANDARD("#TM - Time: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_TIME)); // = "HPM_1"
PRINT_STANDARD("#CY - CLKs: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE)); // = "HPM_2"
PRINT_STANDARD("#03 - Compr.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3));
PRINT_STANDARD("#04 - IF wait: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4));
PRINT_STANDARD("#05 - II wait: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5));
PRINT_STANDARD("#06 - ALU wait: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6));
PRINT_STANDARD("#07 - Loads: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7));
PRINT_STANDARD("#08 - Stores: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8));
PRINT_STANDARD("#09 - MEM wait: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9));
PRINT_STANDARD("#10 - Jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10));
PRINT_STANDARD("#11 - Branches: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11));
PRINT_STANDARD("#12 - Taken: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12));
PRINT_STANDARD("#13 - Traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13));
PRINT_STANDARD("#14 - Illegals: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14));
 
 
// ----------------------------------------------------------
// Final test reports
// ----------------------------------------------------------
neorv32_uart_printf("\n\nTest results:\nOK: %i/%i\nFAILED: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test);
PRINT_CRITICAL("\n\nTest results:\nPASS: %i/%i\nFAIL: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test);
 
// final result
if (cnt_fail == 0) {
neorv32_uart_printf("%c[1m[CPU TEST COMPLETED SUCCESSFULLY!]%c[0m\n", 27, 27);
return 0;
PRINT_STANDARD("%c[1m[CPU TEST COMPLETED SUCCESSFULLY!]%c[0m\n", 27, 27);
}
else {
neorv32_uart_printf("%c[1m[CPU TEST FAILED!]%c[0m\n", 27, 27);
return 1;
PRINT_STANDARD("%c[1m[CPU TEST FAILED!]%c[0m\n", 27, 27);
}
 
return (int)cnt_fail; // return error counter for after-main handler
}
 
 
1724,20 → 1674,57
 
 
/**********************************************************************//**
* XIRQ handler channel 0.
**************************************************************************/
void xirq_trap_handler0(void) {
 
xirq_trap_handler_ack += 2;
}
 
 
/**********************************************************************//**
* XIRQ handler channel 1.
**************************************************************************/
void xirq_trap_handler1(void) {
 
xirq_trap_handler_ack *= 2;
}
 
 
/**********************************************************************//**
* Test results helper function: Shows "[ok]" and increments global cnt_ok
**************************************************************************/
void test_ok(void) {
 
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
PRINT_STANDARD("%c[1m[ok]%c[0m\n", 27, 27);
cnt_ok++;
}
 
 
/**********************************************************************//**
* Test results helper function: Shows "[FAILED]" and increments global cnt_fail
* Test results helper function: Shows "[FAIL]" and increments global cnt_fail
**************************************************************************/
void test_fail(void) {
 
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
PRINT_CRITICAL("%c[1m[FAIL]%c[0m\n", 27, 27);
cnt_fail++;
}
 
 
/**********************************************************************//**
* "after-main" handler that is executed after the application's
* main function returns (called by crt0.S start-up code): Output minimal
* test report to physical UART
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
 
// make sure sim mode is disabled and UARTs are actually enabled
UART0_CT |= (1 << UART_CT_EN);
UART0_CT &= ~(1 << UART_CT_SIM_MODE);
UART1_CT = UART0_CT;
 
// minimal result report
PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test);
 
return 0;
}
/image_gen/image_gen.cpp
58,7 → 58,7
 
FILE *input, *output;
unsigned char buffer[4];
char tmp_string[512];
char tmp_string[1024];
uint32_t tmp = 0, size = 0, checksum = 0;
unsigned int i = 0;
int option = 0;
89,7 → 89,13
return 3;
}
 
// get input file size
fseek(input, 0L, SEEK_END);
unsigned int input_size = (unsigned int)ftell(input);
rewind(input);
unsigned int input_words = input_size / 4;
 
 
// ------------------------------------------------------------
// Get size of application (in bytes)
// ------------------------------------------------------------
174,14 → 180,17
// header
sprintf(tmp_string, "-- The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32\n"
"-- Auto-generated memory init file (for APPLICATION) from source file <%s/%s>\n"
"-- Size: %lu bytes\n"
"\n"
"library ieee;\n"
"use ieee.std_logic_1164.all;\n"
"\n"
"library neorv32;\n"
"use neorv32.neorv32_package.all;\n"
"\n"
"package neorv32_application_image is\n"
"\n"
" type application_init_image_t is array (0 to %lu) of std_ulogic_vector(31 downto 0);\n"
" constant application_init_image : application_init_image_t := (\n", argv[4], argv[2], raw_exe_size/4);
" constant application_init_image : mem32_t := (\n", argv[4], argv[2], raw_exe_size);
fputs(tmp_string, output);
 
// data
190,12 → 199,33
buffer[2] = 0;
buffer[3] = 0;
i = 0;
while(fread(&buffer, sizeof(unsigned char), 4, input) != 0) {
 
while (i < (input_words-1)) {
if (fread(&buffer, sizeof(unsigned char), 4, input) != 0) {
tmp = (uint32_t)(buffer[0] << 0);
tmp |= (uint32_t)(buffer[1] << 8);
tmp |= (uint32_t)(buffer[2] << 16);
tmp |= (uint32_t)(buffer[3] << 24);
sprintf(tmp_string, " %08d => x\"%08x\",\n", i, (unsigned int)tmp);
fputs(tmp_string, output);
buffer[0] = 0;
buffer[1] = 0;
buffer[2] = 0;
buffer[3] = 0;
i++;
}
else {
printf("Unexpected input file end!\n");
break;
}
}
 
if (fread(&buffer, sizeof(unsigned char), 4, input) != 0) {
tmp = (uint32_t)(buffer[0] << 0);
tmp |= (uint32_t)(buffer[1] << 8);
tmp |= (uint32_t)(buffer[2] << 16);
tmp |= (uint32_t)(buffer[3] << 24);
sprintf(tmp_string, " %08d => x\"%08x\",\n", i, tmp);
sprintf(tmp_string, " %08d => x\"%08x\"\n", i, (unsigned int)tmp);
fputs(tmp_string, output);
buffer[0] = 0;
buffer[1] = 0;
203,10 → 233,10
buffer[3] = 0;
i++;
}
else {
printf("Unexpected input file end!\n");
}
 
sprintf(tmp_string, " others => x\"00000000\"\n");
fputs(tmp_string, output);
 
// end
sprintf(tmp_string, " );\n"
"\n"
223,28 → 253,52
// header
sprintf(tmp_string, "-- The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32\n"
"-- Auto-generated memory init file (for BOOTLOADER) from source file <%s/%s>\n"
"-- Size: %lu bytes\n"
"\n"
"library ieee;\n"
"use ieee.std_logic_1164.all;\n"
"\n"
"library neorv32;\n"
"use neorv32.neorv32_package.all;\n"
"\n"
"package neorv32_bootloader_image is\n"
"\n"
" type bootloader_init_image_t is array (0 to %lu) of std_ulogic_vector(31 downto 0);\n"
" constant bootloader_init_image : bootloader_init_image_t := (\n", argv[4], argv[2], raw_exe_size/4);
" constant bootloader_init_image : mem32_t := (\n", argv[4], argv[2], raw_exe_size);
fputs(tmp_string, output);
 
// data
// data
buffer[0] = 0;
buffer[1] = 0;
buffer[2] = 0;
buffer[3] = 0;
i = 0;
while(fread(&buffer, sizeof(unsigned char), 4, input) != 0) {
 
while (i < (input_words-1)) {
if (fread(&buffer, sizeof(unsigned char), 4, input) != 0) {
tmp = (uint32_t)(buffer[0] << 0);
tmp |= (uint32_t)(buffer[1] << 8);
tmp |= (uint32_t)(buffer[2] << 16);
tmp |= (uint32_t)(buffer[3] << 24);
sprintf(tmp_string, " %08d => x\"%08x\",\n", i, (unsigned int)tmp);
fputs(tmp_string, output);
buffer[0] = 0;
buffer[1] = 0;
buffer[2] = 0;
buffer[3] = 0;
i++;
}
else {
printf("Unexpected input file end!\n");
break;
}
}
 
if (fread(&buffer, sizeof(unsigned char), 4, input) != 0) {
tmp = (uint32_t)(buffer[0] << 0);
tmp |= (uint32_t)(buffer[1] << 8);
tmp |= (uint32_t)(buffer[2] << 16);
tmp |= (uint32_t)(buffer[3] << 24);
sprintf(tmp_string, " %08d => x\"%08x\",\n", i, tmp);
sprintf(tmp_string, " %08d => x\"%08x\"\n", i, (unsigned int)tmp);
fputs(tmp_string, output);
buffer[0] = 0;
buffer[1] = 0;
252,10 → 306,10
buffer[3] = 0;
i++;
}
else {
printf("Unexpected input file end!\n");
}
 
sprintf(tmp_string, " others => x\"00000000\"\n");
fputs(tmp_string, output);
 
// end
sprintf(tmp_string, " );\n"
"\n"
/lib/include/neorv32.h
43,6 → 43,11
#ifndef neorv32_h
#define neorv32_h
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
// Standard libraries
#include <stdint.h>
#include <inttypes.h>
53,9 → 58,9
* Available CPU Control and Status Registers (CSRs)
**************************************************************************/
enum NEORV32_CSR_enum {
CSR_FFLAGS = 0x001, /**< 0x001 - fflags (r/w): Floating-point accrued exception flags */
CSR_FRM = 0x002, /**< 0x002 - frm (r/w): Floating-point dynamic rounding mode */
CSR_FCSR = 0x003, /**< 0x003 - fcsr (r/w): Floating-point control/staturs register (frm + fflags) */
CSR_FFLAGS = 0x001, /**< 0x001 - fflags (r/w): Floating-point accrued exception flags */
CSR_FRM = 0x002, /**< 0x002 - frm (r/w): Floating-point dynamic rounding mode */
CSR_FCSR = 0x003, /**< 0x003 - fcsr (r/w): Floating-point control/staturs register (frm + fflags) */
 
CSR_MSTATUS = 0x300, /**< 0x300 - mstatus (r/w): Machine status register */
CSR_MISA = 0x301, /**< 0x301 - misa (r/-): CPU ISA and extensions (read-only in NEORV32) */
183,8 → 188,8
CSR_PMPADDR62 = 0x3ee, /**< 0x3ee - pmpaddr62 (r/w): Physical memory protection address register 62 */
CSR_PMPADDR63 = 0x3ef, /**< 0x3ef - pmpaddr63 (r/w): Physical memory protection address register 63 */
 
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */
 
CSR_MHPMCOUNTER3 = 0xb03, /**< 0xb03 - mhpmcounter3 (r/w): Machine hardware performance monitor 3 counter low word */
CSR_MHPMCOUNTER4 = 0xb04, /**< 0xb04 - mhpmcounter4 (r/w): Machine hardware performance monitor 4 counter low word */
216,8 → 221,8
CSR_MHPMCOUNTER30 = 0xb1e, /**< 0xb1e - mhpmcounter30 (r/w): Machine hardware performance monitor 30 counter low word */
CSR_MHPMCOUNTER31 = 0xb1f, /**< 0xb1f - mhpmcounter31 (r/w): Machine hardware performance monitor 31 counter low word */
 
CSR_MCYCLEH = 0xb80, /**< 0xb80 - mcycleh (r/w): Machine cycle counter high word */
CSR_MINSTRETH = 0xb82, /**< 0xb82 - minstreth (r/w): Machine instructions-retired counter high word */
CSR_MCYCLEH = 0xb80, /**< 0xb80 - mcycleh (r/w): Machine cycle counter high word */
CSR_MINSTRETH = 0xb82, /**< 0xb82 - minstreth (r/w): Machine instructions-retired counter high word */
 
CSR_MHPMCOUNTER3H = 0xb83, /**< 0xb83 - mhpmcounter3h (r/w): Machine hardware performance monitor 3 counter high word */
CSR_MHPMCOUNTER4H = 0xb84, /**< 0xb84 - mhpmcounter4h (r/w): Machine hardware performance monitor 4 counter high word */
249,74 → 254,14
CSR_MHPMCOUNTER30H = 0xb9e, /**< 0xb9e - mhpmcounter30h (r/w): Machine hardware performance monitor 30 counter high word */
CSR_MHPMCOUNTER31H = 0xb9f, /**< 0xb9f - mhpmcounter31h (r/w): Machine hardware performance monitor 31 counter high word */
 
CSR_CYCLE = 0xc00, /**< 0xc00 - cycle (r/-): Cycle counter low word (from MCYCLE) */
CSR_TIME = 0xc01, /**< 0xc01 - time (r/-): Timer low word (from MTIME.TIME_LO) */
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */
CSR_CYCLE = 0xc00, /**< 0xc00 - cycle (r/-): Cycle counter low word (from MCYCLE) */
CSR_TIME = 0xc01, /**< 0xc01 - time (r/-): Timer low word (from MTIME.TIME_LO) */
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */
 
CSR_HPMCOUNTER3 = 0xc03, /**< 0xc03 - hpmcounter3 (r/w): Hardware performance monitor 3 counter low word */
CSR_HPMCOUNTER4 = 0xc04, /**< 0xc04 - hpmcounter4 (r/w): Hardware performance monitor 4 counter low word */
CSR_HPMCOUNTER5 = 0xc05, /**< 0xc05 - hpmcounter5 (r/w): Hardware performance monitor 5 counter low word */
CSR_HPMCOUNTER6 = 0xc06, /**< 0xc06 - hpmcounter6 (r/w): Hardware performance monitor 6 counter low word */
CSR_HPMCOUNTER7 = 0xc07, /**< 0xc07 - hpmcounter7 (r/w): Hardware performance monitor 7 counter low word */
CSR_HPMCOUNTER8 = 0xc08, /**< 0xc08 - hpmcounter8 (r/w): Hardware performance monitor 8 counter low word */
CSR_HPMCOUNTER9 = 0xc09, /**< 0xc09 - hpmcounter9 (r/w): Hardware performance monitor 9 counter low word */
CSR_HPMCOUNTER10 = 0xc0a, /**< 0xc0a - hpmcounter10 (r/w): Hardware performance monitor 10 counter low word */
CSR_HPMCOUNTER11 = 0xc0b, /**< 0xc0b - hpmcounter11 (r/w): Hardware performance monitor 11 counter low word */
CSR_HPMCOUNTER12 = 0xc0c, /**< 0xc0c - hpmcounter12 (r/w): Hardware performance monitor 12 counter low word */
CSR_HPMCOUNTER13 = 0xc0d, /**< 0xc0d - hpmcounter13 (r/w): Hardware performance monitor 13 counter low word */
CSR_HPMCOUNTER14 = 0xc0e, /**< 0xc0e - hpmcounter14 (r/w): Hardware performance monitor 14 counter low word */
CSR_HPMCOUNTER15 = 0xc0f, /**< 0xc0f - hpmcounter15 (r/w): Hardware performance monitor 15 counter low word */
CSR_HPMCOUNTER16 = 0xc10, /**< 0xc10 - hpmcounter16 (r/w): Hardware performance monitor 16 counter low word */
CSR_HPMCOUNTER17 = 0xc11, /**< 0xc11 - hpmcounter17 (r/w): Hardware performance monitor 17 counter low word */
CSR_HPMCOUNTER18 = 0xc12, /**< 0xc12 - hpmcounter18 (r/w): Hardware performance monitor 18 counter low word */
CSR_HPMCOUNTER19 = 0xc13, /**< 0xc13 - hpmcounter19 (r/w): Hardware performance monitor 19 counter low word */
CSR_HPMCOUNTER20 = 0xc14, /**< 0xc14 - hpmcounter20 (r/w): Hardware performance monitor 20 counter low word */
CSR_HPMCOUNTER21 = 0xc15, /**< 0xc15 - hpmcounter21 (r/w): Hardware performance monitor 21 counter low word */
CSR_HPMCOUNTER22 = 0xc16, /**< 0xc16 - hpmcounter22 (r/w): Hardware performance monitor 22 counter low word */
CSR_HPMCOUNTER23 = 0xc17, /**< 0xc17 - hpmcounter23 (r/w): Hardware performance monitor 23 counter low word */
CSR_HPMCOUNTER24 = 0xc18, /**< 0xc18 - hpmcounter24 (r/w): Hardware performance monitor 24 counter low word */
CSR_HPMCOUNTER25 = 0xc19, /**< 0xc19 - hpmcounter25 (r/w): Hardware performance monitor 25 counter low word */
CSR_HPMCOUNTER26 = 0xc1a, /**< 0xc1a - hpmcounter26 (r/w): Hardware performance monitor 26 counter low word */
CSR_HPMCOUNTER27 = 0xc1b, /**< 0xc1b - hpmcounter27 (r/w): Hardware performance monitor 27 counter low word */
CSR_HPMCOUNTER28 = 0xc1c, /**< 0xc1c - hpmcounter28 (r/w): Hardware performance monitor 28 counter low word */
CSR_HPMCOUNTER29 = 0xc1d, /**< 0xc1d - hpmcounter29 (r/w): Hardware performance monitor 29 counter low word */
CSR_HPMCOUNTER30 = 0xc1e, /**< 0xc1e - hpmcounter30 (r/w): Hardware performance monitor 30 counter low word */
CSR_HPMCOUNTER31 = 0xc1f, /**< 0xc1f - hpmcounter31 (r/w): Hardware performance monitor 31 counter low word */
CSR_CYCLEH = 0xc80, /**< 0xc80 - cycleh (r/-): Cycle counter high word (from MCYCLEH) */
CSR_TIMEH = 0xc81, /**< 0xc81 - timeh (r/-): Timer high word (from MTIME.TIME_HI) */
CSR_INSTRETH = 0xc82, /**< 0xc82 - instreth (r/-): Instructions-retired counter high word (from MINSTRETH) */
 
CSR_CYCLEH = 0xc80, /**< 0xc80 - cycleh (r/-): Cycle counter high word (from MCYCLEH) */
CSR_TIMEH = 0xc81, /**< 0xc81 - timeh (r/-): Timer high word (from MTIME.TIME_HI) */
CSR_INSTRETH = 0xc82, /**< 0xc82 - instreth (r/-): Instructions-retired counter high word (from MINSTRETH) */
 
CSR_HPMCOUNTER3H = 0xc83, /**< 0xc83 - hpmcounter3h (r/w): Hardware performance monitor 3 counter high word */
CSR_HPMCOUNTER4H = 0xc84, /**< 0xc84 - hpmcounter4h (r/w): Hardware performance monitor 4 counter high word */
CSR_HPMCOUNTER5H = 0xc85, /**< 0xc85 - hpmcounter5h (r/w): Hardware performance monitor 5 counter high word */
CSR_HPMCOUNTER6H = 0xc86, /**< 0xc86 - hpmcounter6h (r/w): Hardware performance monitor 6 counter high word */
CSR_HPMCOUNTER7H = 0xc87, /**< 0xc87 - hpmcounter7h (r/w): Hardware performance monitor 7 counter high word */
CSR_HPMCOUNTER8H = 0xc88, /**< 0xc88 - hpmcounter8h (r/w): Hardware performance monitor 8 counter high word */
CSR_HPMCOUNTER9H = 0xc89, /**< 0xc89 - hpmcounter9h (r/w): Hardware performance monitor 9 counter high word */
CSR_HPMCOUNTER10H = 0xc8a, /**< 0xc8a - hpmcounter10h (r/w): Hardware performance monitor 10 counter high word */
CSR_HPMCOUNTER11H = 0xc8b, /**< 0xc8b - hpmcounter11h (r/w): Hardware performance monitor 11 counter high word */
CSR_HPMCOUNTER12H = 0xc8c, /**< 0xc8c - hpmcounter12h (r/w): Hardware performance monitor 12 counter high word */
CSR_HPMCOUNTER13H = 0xc8d, /**< 0xc8d - hpmcounter13h (r/w): Hardware performance monitor 13 counter high word */
CSR_HPMCOUNTER14H = 0xc8e, /**< 0xc8e - hpmcounter14h (r/w): Hardware performance monitor 14 counter high word */
CSR_HPMCOUNTER15H = 0xc8f, /**< 0xc8f - hpmcounter15h (r/w): Hardware performance monitor 15 counter high word */
CSR_HPMCOUNTER16H = 0xc90, /**< 0xc90 - hpmcounter16h (r/w): Hardware performance monitor 16 counter high word */
CSR_HPMCOUNTER17H = 0xc91, /**< 0xc91 - hpmcounter17h (r/w): Hardware performance monitor 17 counter high word */
CSR_HPMCOUNTER18H = 0xc92, /**< 0xc92 - hpmcounter18h (r/w): Hardware performance monitor 18 counter high word */
CSR_HPMCOUNTER19H = 0xc93, /**< 0xc93 - hpmcounter19h (r/w): Hardware performance monitor 19 counter high word */
CSR_HPMCOUNTER20H = 0xc94, /**< 0xc94 - hpmcounter20h (r/w): Hardware performance monitor 20 counter high word */
CSR_HPMCOUNTER21H = 0xc95, /**< 0xc95 - hpmcounter21h (r/w): Hardware performance monitor 21 counter high word */
CSR_HPMCOUNTER22H = 0xc96, /**< 0xc96 - hpmcounter22h (r/w): Hardware performance monitor 22 counter high word */
CSR_HPMCOUNTER23H = 0xc97, /**< 0xc97 - hpmcounter23h (r/w): Hardware performance monitor 23 counter high word */
CSR_HPMCOUNTER24H = 0xc98, /**< 0xc98 - hpmcounter24h (r/w): Hardware performance monitor 24 counter high word */
CSR_HPMCOUNTER25H = 0xc99, /**< 0xc99 - hpmcounter25h (r/w): Hardware performance monitor 25 counter high word */
CSR_HPMCOUNTER26H = 0xc9a, /**< 0xc9a - hpmcounter26h (r/w): Hardware performance monitor 26 counter high word */
CSR_HPMCOUNTER27H = 0xc9b, /**< 0xc9b - hpmcounter27h (r/w): Hardware performance monitor 27 counter high word */
CSR_HPMCOUNTER28H = 0xc9c, /**< 0xc9c - hpmcounter28h (r/w): Hardware performance monitor 28 counter high word */
CSR_HPMCOUNTER29H = 0xc9d, /**< 0xc9d - hpmcounter29h (r/w): Hardware performance monitor 29 counter high word */
CSR_HPMCOUNTER30H = 0xc9e, /**< 0xc9e - hpmcounter30h (r/w): Hardware performance monitor 30 counter high word */
CSR_HPMCOUNTER31H = 0xc9f, /**< 0xc9f - hpmcounter31h (r/w): Hardware performance monitor 31 counter high word */
 
CSR_MVENDORID = 0xf11, /**< 0xf11 - mvendorid (r/-): Vendor ID */
CSR_MARCHID = 0xf12, /**< 0xf12 - marchid (r/-): Architecture ID */
CSR_MIMPID = 0xf13, /**< 0xf13 - mimpid (r/-): Implementation ID/version */
341,39 → 286,9
* CPU <b>mcounteren</b> CSR (r/w): Machine counter enable (RISC-V spec.)
**************************************************************************/
enum NEORV32_CSR_MCOUNTEREN_enum {
CSR_MCOUNTEREN_CY = 0, /**< CPU mcounteren CSR (0): CY - Allow access to cycle[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_TM = 1, /**< CPU mcounteren CSR (1): TM - Allow access to time[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_IR = 2, /**< CPU mcounteren CSR (2): IR - Allow access to instret[h] CSRs from U-mode when set (r/w) */
 
CSR_MCOUNTEREN_HPM3 = 3, /**< CPU mcounteren CSR (3): HPM3 - Allow access to hpmcnt3[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM4 = 4, /**< CPU mcounteren CSR (4): HPM4 - Allow access to hpmcnt4[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM5 = 5, /**< CPU mcounteren CSR (5): HPM5 - Allow access to hpmcnt5[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM6 = 6, /**< CPU mcounteren CSR (6): HPM6 - Allow access to hpmcnt6[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM7 = 7, /**< CPU mcounteren CSR (7): HPM7 - Allow access to hpmcnt7[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM8 = 8, /**< CPU mcounteren CSR (8): HPM8 - Allow access to hpmcnt8[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM9 = 9, /**< CPU mcounteren CSR (9): HPM9 - Allow access to hpmcnt9[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM10 = 10, /**< CPU mcounteren CSR (10): HPM10 - Allow access to hpmcnt10[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM11 = 11, /**< CPU mcounteren CSR (11): HPM11 - Allow access to hpmcnt11[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM12 = 12, /**< CPU mcounteren CSR (12): HPM12 - Allow access to hpmcnt12[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM13 = 13, /**< CPU mcounteren CSR (13): HPM13 - Allow access to hpmcnt13[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM14 = 14, /**< CPU mcounteren CSR (14): HPM14 - Allow access to hpmcnt14[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM15 = 15, /**< CPU mcounteren CSR (15): HPM15 - Allow access to hpmcnt15[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM16 = 16, /**< CPU mcounteren CSR (16): HPM16 - Allow access to hpmcnt16[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM17 = 17, /**< CPU mcounteren CSR (17): HPM17 - Allow access to hpmcnt17[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM18 = 18, /**< CPU mcounteren CSR (18): HPM18 - Allow access to hpmcnt18[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM19 = 19, /**< CPU mcounteren CSR (19): HPM19 - Allow access to hpmcnt19[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM20 = 20, /**< CPU mcounteren CSR (20): HPM20 - Allow access to hpmcnt20[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM21 = 21, /**< CPU mcounteren CSR (21): HPM21 - Allow access to hpmcnt21[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM22 = 22, /**< CPU mcounteren CSR (22): HPM22 - Allow access to hpmcnt22[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM23 = 23, /**< CPU mcounteren CSR (23): HPM23 - Allow access to hpmcnt23[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM24 = 24, /**< CPU mcounteren CSR (24): HPM24 - Allow access to hpmcnt24[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM25 = 25, /**< CPU mcounteren CSR (25): HPM25 - Allow access to hpmcnt25[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM26 = 26, /**< CPU mcounteren CSR (26): HPM26 - Allow access to hpmcnt26[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM27 = 27, /**< CPU mcounteren CSR (27): HPM27 - Allow access to hpmcnt27[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM28 = 28, /**< CPU mcounteren CSR (28): HPM28 - Allow access to hpmcnt28[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM29 = 29, /**< CPU mcounteren CSR (29): HPM29 - Allow access to hpmcnt29[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM30 = 30, /**< CPU mcounteren CSR (30): HPM30 - Allow access to hpmcnt30[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_HPM31 = 31 /**< CPU mcounteren CSR (31): HPM31 - Allow access to hpmcnt31[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_CY = 0, /**< CPU mcounteren CSR (0): CY - Allow access to cycle[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_TM = 1, /**< CPU mcounteren CSR (1): TM - Allow access to time[h] CSRs from U-mode when set (r/w) */
CSR_MCOUNTEREN_IR = 2 /**< CPU mcounteren CSR (2): IR - Allow access to instret[h] CSRs from U-mode when set (r/w) */
};
 
 
459,7 → 374,6
CSR_MIP_FIRQ5P = 21, /**< CPU mip CSR (21): FIRQ5P - Fast interrupt channel 5 pending (r/-) */
CSR_MIP_FIRQ6P = 22, /**< CPU mip CSR (22): FIRQ6P - Fast interrupt channel 6 pending (r/-) */
CSR_MIP_FIRQ7P = 23, /**< CPU mip CSR (23): FIRQ7P - Fast interrupt channel 7 pending (r/-) */
 
CSR_MIP_FIRQ8P = 24, /**< CPU mip CSR (24): FIRQ8P - Fast interrupt channel 8 pending (r/-) */
CSR_MIP_FIRQ9P = 25, /**< CPU mip CSR (25): FIRQ9P - Fast interrupt channel 9 pending (r/-) */
CSR_MIP_FIRQ10P = 26, /**< CPU mip CSR (26): FIRQ10P - Fast interrupt channel 10 pending (r/-) */
475,18 → 389,18
* CPU <b>misa</b> CSR (r/-): Machine instruction set extensions (RISC-V spec.)
**************************************************************************/
enum NEORV32_CSR_MISA_enum {
CSR_MISA_A_EXT = 0, /**< CPU misa CSR (0): A: Atomic instructions CPU extension available (r/-)*/
CSR_MISA_B_EXT = 1, /**< CPU misa CSR (1): B: Bit manipulation CPU extension available (r/-)*/
CSR_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/-)*/
CSR_MISA_D_EXT = 3, /**< CPU misa CSR (3): D: Double-precision floating-point extension available (r/-)*/
CSR_MISA_E_EXT = 4, /**< CPU misa CSR (4): E: Embedded CPU extension available (r/-) */
CSR_MISA_F_EXT = 5, /**< CPU misa CSR (5): F: Single-precision floating-point extension available (r/-)*/
CSR_MISA_I_EXT = 8, /**< CPU misa CSR (8): I: Base integer ISA CPU extension available (r/-) */
CSR_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/-)*/
CSR_MISA_U_EXT = 20, /**< CPU misa CSR (20): U: User mode CPU extension available (r/-)*/
CSR_MISA_X_EXT = 23, /**< CPU misa CSR (23): X: Non-standard CPU extension available (r/-) */
CSR_MISA_MXL_LO_EXT = 30, /**< CPU misa CSR (30): MXL.lo: CPU data width (r/-) */
CSR_MISA_MXL_HI_EXT = 31 /**< CPU misa CSR (31): MXL.Hi: CPU data width (r/-) */
CSR_MISA_A = 0, /**< CPU misa CSR (0): A: Atomic instructions CPU extension available (r/-)*/
CSR_MISA_B = 1, /**< CPU misa CSR (1): B: Bit manipulation CPU extension available (r/-)*/
CSR_MISA_C = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/-)*/
CSR_MISA_D = 3, /**< CPU misa CSR (3): D: Double-precision floating-point extension available (r/-)*/
CSR_MISA_E = 4, /**< CPU misa CSR (4): E: Embedded CPU extension available (r/-) */
CSR_MISA_F = 5, /**< CPU misa CSR (5): F: Single-precision floating-point extension available (r/-)*/
CSR_MISA_I = 8, /**< CPU misa CSR (8): I: Base integer ISA CPU extension available (r/-) */
CSR_MISA_M = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/-)*/
CSR_MISA_U = 20, /**< CPU misa CSR (20): U: User mode CPU extension available (r/-)*/
CSR_MISA_X = 23, /**< CPU misa CSR (23): X: Non-standard CPU extension available (r/-) */
CSR_MISA_MXL_LO = 30, /**< CPU misa CSR (30): MXL.lo: CPU data width (r/-) */
CSR_MISA_MXL_HI = 31 /**< CPU misa CSR (31): MXL.Hi: CPU data width (r/-) */
};
 
 
496,9 → 410,8
enum NEORV32_CSR_MZEXT_enum {
CSR_MZEXT_ZICSR = 0, /**< CPU mzext CSR (0): Zicsr extension (I sub-extension) available when set (r/-) */
CSR_MZEXT_ZIFENCEI = 1, /**< CPU mzext CSR (1): Zifencei extension (I sub-extension) available when set (r/-) */
//CSR_MZEXT_ZBB = 2, /**< CPU mzext CSR (2): Zbb extension (B sub-extension) available when set (r/-) */
//CSR_MZEXT_ZBS = 3, /**< CPU mzext CSR (3): Zbs extension (B sub-extension) available when set (r/-) */
//CSR_MZEXT_ZBA = 4, /**< CPU mzext CSR (4): Zba extension (B sub-extension) available when set (r/-) */
CSR_MZEXT_ZMMUL = 2, /**< CPU mzext CSR (2): Zmmul extension (M sub-extension) available when set (r/-) */
 
CSR_MZEXT_ZFINX = 5, /**< CPU mzext CSR (5): Zfinx extension (F sub-/alternative-extension) available when set (r/-) */
CSR_MZEXT_ZXSCNT = 6, /**< CPU mzext CSR (6): Custom extension - Small CPU counters: "cycle" & "instret" CSRs have less than 64-bit when set (r/-) */
CSR_MZEXT_ZXNOCNT = 7, /**< CPU mzext CSR (7): Custom extension - NO CPU counters: "cycle" & "instret" CSRs are NOT available at all when set (r/-) */
715,7 → 628,7
**************************************************************************/
/**@{*/
/** PWM base address */
#define PWM_BASE (0XFFFFFF80UL) // /**< PWM base address */
#define PWM_BASE (0xFFFFFE80UL) // /**< PWM base address */
/** PWM address space size in bytes */
#define PWM_SIZE (16*4) // /**< PWM address space size in bytes */
 
763,68 → 676,93
 
 
/**********************************************************************//**
* @name IO Device: General Purpose Input/Output Port Unit (GPIO)
* @name IO Device: Stream link interface (SLINK)
**************************************************************************/
/**@{*/
/** GPIO base address */
#define GPIO_BASE (0xFFFFFF80UL) // /**< GPIO base address */
/** GPIO address space size in bytes */
#define GPIO_SIZE (2*4) // /**< GPIO address space size in bytes */
/** SLINK base address */
#define SLINK_BASE (0xFFFFFEC0UL) // /**< SLINK base address */
/** SLINK address space size in bytes */
#define SLINK_SIZE (16*4) // /**< SLINK address space size in bytes */
 
/** read access: GPIO parallel input port 32-bit (r/-), write_access: pin-change IRQ for each input pin (-/w) */
#define GPIO_INPUT (*(IO_REG32 (GPIO_BASE + 0)))
/** GPIO parallel output port 32-bit (r/w) */
#define GPIO_OUTPUT (*(IO_REG32 (GPIO_BASE + 4)))
/**@}*/
/** SLINK control register (r/w) */
#define SLINK_CT (*(IO_REG32 (SLINK_BASE + 0))) // r/w: control register
/** stream link 0 (r/w) */
#define SLINK_CH0 (*(IO_REG32 (SLINK_BASE + 32 + 0))) // r/w: link 0
/** stream link 1 (r/w) */
#define SLINK_CH1 (*(IO_REG32 (SLINK_BASE + 32 + 4))) // r/w: link 1
/** stream link 2 (r/w) */
#define SLINK_CH2 (*(IO_REG32 (SLINK_BASE + 32 + 8))) // r/w: link 2
/** stream link 3 (r/w) */
#define SLINK_CH3 (*(IO_REG32 (SLINK_BASE + 32 + 12))) // r/w: link 3
/** stream link 4 (r/w) */
#define SLINK_CH4 (*(IO_REG32 (SLINK_BASE + 32 + 16))) // r/w: link 4
/** stream link 5 (r/w) */
#define SLINK_CH5 (*(IO_REG32 (SLINK_BASE + 32 + 20))) // r/w: link 5
/** stream link 6 (r/w) */
#define SLINK_CH6 (*(IO_REG32 (SLINK_BASE + 32 + 24))) // r/w: link 6
/** stream link 7 (r/w) */
#define SLINK_CH7 (*(IO_REG32 (SLINK_BASE + 32 + 28))) // r/w: link 7
 
/** SLINK control register bits */
enum NEORV32_SLINK_CT_enum {
SLINK_CT_RX0_AVAIL = 0, /**< SLINK control register(0) (r/-): RX link 0 data available */
SLINK_CT_RX1_AVAIL = 1, /**< SLINK control register(1) (r/-): RX link 1 data available */
SLINK_CT_RX2_AVAIL = 2, /**< SLINK control register(2) (r/-): RX link 2 data available */
SLINK_CT_RX3_AVAIL = 3, /**< SLINK control register(3) (r/-): RX link 3 data available */
SLINK_CT_RX4_AVAIL = 4, /**< SLINK control register(4) (r/-): RX link 4 data available */
SLINK_CT_RX5_AVAIL = 5, /**< SLINK control register(5) (r/-): RX link 5 data available */
SLINK_CT_RX6_AVAIL = 6, /**< SLINK control register(6) (r/-): RX link 6 data available */
SLINK_CT_RX7_AVAIL = 7, /**< SLINK control register(7) (r/-): RX link 7 data available */
 
/**********************************************************************//**
* @name IO Device: True Random Number Generator (TRNG)
**************************************************************************/
/**@{*/
/** TRNG base address */
#define TRNG_BASE (0xFFFFFF88UL) // /**< TRNG base address */
/** TRNG address space size in bytes */
#define TRNG_SIZE (1*4) // /**< TRNG address space size in bytes */
SLINK_CT_TX0_FREE = 8, /**< SLINK control register(8) (r/-): RT link 0 ready to send */
SLINK_CT_TX1_FREE = 9, /**< SLINK control register(9) (r/-): RT link 1 ready to send */
SLINK_CT_TX2_FREE = 10, /**< SLINK control register(10) (r/-): RT link 2 ready to send */
SLINK_CT_TX3_FREE = 11, /**< SLINK control register(11) (r/-): RT link 3 ready to send */
SLINK_CT_TX4_FREE = 12, /**< SLINK control register(12) (r/-): RT link 4 ready to send */
SLINK_CT_TX5_FREE = 13, /**< SLINK control register(13) (r/-): RT link 5 ready to send */
SLINK_CT_TX6_FREE = 14, /**< SLINK control register(14) (r/-): RT link 6 ready to send */
SLINK_CT_TX7_FREE = 15, /**< SLINK control register(15) (r/-): RT link 7 ready to send */
 
/** TRNG control/data register (r/w) */
#define TRNG_CT (*(IO_REG32 (TRNG_BASE + 0)))
SLINK_CT_RX_NUM0 = 16, /**< SLINK control register(16) (r/-): number of implemented RX links -1 bit 0 */
SLINK_CT_RX_NUM1 = 17, /**< SLINK control register(17) (r/-): number of implemented RX links -1 bit 1 */
SLINK_CT_RX_NUM2 = 18, /**< SLINK control register(18) (r/-): number of implemented RX links -1 bit 2 */
 
/** TRNG control/data register bits */
enum NEORV32_TRNG_CT_enum {
TRNG_CT_DATA_LSB = 0, /**< TRNG data/control register(0) (r/-): Random data byte LSB */
TRNG_CT_DATA_MSB = 7, /**< TRNG data/control register(7) (r/-): Random data byte MSB */
SLINK_CT_TX_NUM0 = 19, /**< SLINK control register(19) (r/-): number of implemented TX links -1bit 0 */
SLINK_CT_TX_NUM1 = 20, /**< SLINK control register(20) (r/-): number of implemented TX links -1bit 1 */
SLINK_CT_TX_NUM2 = 21, /**< SLINK control register(21) (r/-): number of implemented TX links -1bit 2 */
 
TRNG_CT_EN = 30, /**< TRNG data/control register(30) (r/w): TRNG enable */
TRNG_CT_VALID = 31 /**< TRNG data/control register(31) (r/-): Random data output valid */
SLINK_CT_RX_FIFO_S0 = 22, /**< SLINK control register(22) (r/-): log2(RX FIFO size) bit 0 */
SLINK_CT_RX_FIFO_S1 = 23, /**< SLINK control register(23) (r/-): log2(RX FIFO size) bit 1 */
SLINK_CT_RX_FIFO_S2 = 24, /**< SLINK control register(24) (r/-): log2(RX FIFO size) bit 2 */
SLINK_CT_RX_FIFO_S3 = 25, /**< SLINK control register(25) (r/-): log2(RX FIFO size) bit 3 */
 
SLINK_CT_TX_FIFO_S0 = 26, /**< SLINK control register(26) (r/-): log2(TX FIFO size) bit 0 */
SLINK_CT_TX_FIFO_S1 = 27, /**< SLINK control register(27) (r/-): log2(TX FIFO size) bit 1 */
SLINK_CT_TX_FIFO_S2 = 28, /**< SLINK control register(28) (r/-): log2(TX FIFO size) bit 2 */
SLINK_CT_TX_FIFO_S3 = 29, /**< SLINK control register(29) (r/-): log2(TX FIFO size) bit 3 */
 
SLINK_CT_EN = 31 /**< SLINK control register(31) (r/w): SLINK controller enable */
};
/**@}*/
 
 
/**********************************************************************//**
* @name IO Device: Watchdog Timer (WDT)
* @name IO Device: External Interrupt Controller (XIRQ)
**************************************************************************/
/**@{*/
/** WDT base address */
#define WDT_BASE (0xFFFFFF8CUL) // /**< WDT base address */
/** WDT address space size in bytes */
#define WDT_SIZE (1*4) // /**< WDT address space size in bytes */
/** XIRQ base address */
#define XIRQ_BASE (0xFFFFFF80UL) // /**< XIRQ base address */
/** XIRQ address space size in bytes */
#define XIRQ_SIZE (4*4) // /**< XIRQ address space size in bytes */
 
/** Watchdog control register (r/w) */
#define WDT_CT (*(IO_REG32 (WDT_BASE + 0)))
 
/** WTD control register bits */
enum NEORV32_WDT_CT_enum {
WDT_CT_EN = 0, /**< WDT control register(0) (r/w): Watchdog enable */
WDT_CT_CLK_SEL0 = 1, /**< WDT control register(1) (r/w): Clock prescaler select bit 0 */
WDT_CT_CLK_SEL1 = 2, /**< WDT control register(2) (r/w): Clock prescaler select bit 1 */
WDT_CT_CLK_SEL2 = 3, /**< WDT control register(3) (r/w): Clock prescaler select bit 2 */
WDT_CT_MODE = 4, /**< WDT control register(4) (r/w): Watchdog mode: 0=timeout causes interrupt, 1=timeout causes processor reset */
WDT_CT_RCAUSE = 5, /**< WDT control register(5) (r/-): Cause of last system reset: 0=external reset, 1=watchdog */
WDT_CT_RESET = 6, /**< WDT control register(6) (-/w): Reset WDT counter when set, auto-clears */
WDT_CT_FORCE = 7, /**< WDT control register(7) (-/w): Force WDT action, auto-clears */
WDT_CT_LOCK = 8 /**< WDT control register(8) (r/w): Lock write access to control register, clears on reset (HW or WDT) only */
};
/** XIRQ IRQ input enable register (r/w) */
#define XIRQ_IER (*(IO_REG32 (XIRQ_BASE + 0)))
/** XIRQ pending IRQ register /ack/clear (r/w) */
#define XIRQ_IPR (*(IO_REG32 (XIRQ_BASE + 4)))
/** EXTIRW (time compare register) low word (r/w) */
#define XIRQ_SCR (*(IO_REG32 (XIRQ_BASE + 8)))
// reserved
//#define XIRQ_reserved (*(IO_REG32 (XIRQ_BASE + 12)))
/**@}*/
 
 
1010,67 → 948,81
 
 
/**********************************************************************//**
* @name IO Device: Numerically-Controlled Oscillator (NCO)
* @name IO Device: True Random Number Generator (TRNG)
**************************************************************************/
/**@{*/
/** NCO base address */
#define NCO_BASE (0xFFFFFFC0UL) // /**< NCO base address */
/** NCO address space size in bytes */
#define NCO_SIZE (4*4) // /**< NCO address space size in bytes */
/** TRNG base address */
#define TRNG_BASE (0xFFFFFFB8UL) // /**< TRNG base address */
/** TRNG address space size in bytes */
#define TRNG_SIZE (1*4) // /**< TRNG address space size in bytes */
 
/** NCO control register (r/w) */
#define NCO_CT (*(IO_REG32 (NCO_BASE + 0))) // r/w: control register
/** NCO channel 0 tuning word (r/w) */
#define NCO_TUNE_CH0 (*(IO_REG32 (NCO_BASE + 4))) // r/w: tuning word channel 0
/** NCO channel 1 tuning word (r/w) */
#define NCO_TUNE_CH1 (*(IO_REG32 (NCO_BASE + 8))) // r/w: tuning word channel 1
/** NCO channel 2 tuning word (r/w) */
#define NCO_TUNE_CH2 (*(IO_REG32 (NCO_BASE + 12))) // r/w: tuning word channel 2
/** TRNG control/data register (r/w) */
#define TRNG_CT (*(IO_REG32 (TRNG_BASE + 0)))
 
/** NCO control register bits */
enum NEORV32_NCO_CT_enum {
NCO_CT_EN = 0, /**< NCO control register(0) (r/w): NCO global enable */
// channel 0
NCO_CT_CH0_MODE = 1, /**< NCO control register(1) - channel 0 (r/w): Output mode (0=fixed 50% duty cycle; 1=pulse mode) */
NCO_CT_CH0_IDLE_POL = 2, /**< NCO control register(2) - channel 0 (r/w): Output idle polarity (0=low, 1=high) */
NCO_CT_CH0_OE = 3, /**< NCO control register(3) - channel 0 (r/w): Enable processor output pin */
NCO_CT_CH0_OUTPUT = 4, /**< NCO control register(4) - channel 0 (r/-): Current channel output state */
NCO_CT_CH0_PRSC0 = 5, /**< NCO control register(5) - channel 0 (r/w): Clock prescaler select bit 0 */
NCO_CT_CH0_PRSC1 = 6, /**< NCO control register(6) - channel 0 (r/w): Clock prescaler select bit 1 */
NCO_CT_CH0_PRSC2 = 7, /**< NCO control register(7) - channel 0 (r/w): Clock prescaler select bit 2 */
NCO_CT_CH0_PULSE0 = 8, /**< NCO control register(8) - channel 0 (r/w): Pulse-mode: Pulse length select bit 0 */
NCO_CT_CH0_PULSE1 = 9, /**< NCO control register(9) - channel 0 (r/w): Pulse-mode: Pulse length select bit 1 */
NCO_CT_CH0_PULSE2 = 10, /**< NCO control register(10) - channel 0 (r/w): Pulse-mode: Pulse length select bit 2 */
// channel 1
NCO_CT_CH1_MODE = 11, /**< NCO control register(11) - channel 1 (r/w): Output mode (0=fixed 50% duty cycle; 1=pulse mode) */
NCO_CT_CH1_IDLE_POL = 12, /**< NCO control register(12) - channel 1 (r/w): Output idle polarity (0=low, 1=high) */
NCO_CT_CH1_OE = 13, /**< NCO control register(13) - channel 1 (r/w): Enable processor output pin */
NCO_CT_CH1_OUTPUT = 14, /**< NCO control register(14) - channel 1 (r/-): Current channel output state */
NCO_CT_CH1_PRSC0 = 15, /**< NCO control register(15) - channel 1 (r/w): Clock prescaler select bit 0 */
NCO_CT_CH1_PRSC1 = 16, /**< NCO control register(16) - channel 1 (r/w): Clock prescaler select bit 1 */
NCO_CT_CH1_PRSC2 = 17, /**< NCO control register(17) - channel 1 (r/w): Clock prescaler select bit 2 */
NCO_CT_CH1_PULSE0 = 18, /**< NCO control register(18) - channel 1 (r/w): Pulse-mode: Pulse length select bit 0 */
NCO_CT_CH1_PULSE1 = 19, /**< NCO control register(19) - channel 1 (r/w): Pulse-mode: Pulse length select bit 1 */
NCO_CT_CH1_PULSE2 = 20, /**< NCO control register(20) - channel 1 (r/w): Pulse-mode: Pulse length select bit 2 */
// channel 2
NCO_CT_CH2_MODE = 21, /**< NCO control register(21) - channel 2 (r/w): Output mode (0=fixed 50% duty cycle; 1=pulse mode) */
NCO_CT_CH2_IDLE_POL = 22, /**< NCO control register(22) - channel 2 (r/w): Output idle polarity (0=low, 1=high) */
NCO_CT_CH2_OE = 23, /**< NCO control register(23) - channel 2 (r/w): Enable processor output pin */
NCO_CT_CH2_OUTPUT = 24, /**< NCO control register(24) - channel 2 (r/-): Current channel output state */
NCO_CT_CH2_PRSC0 = 25, /**< NCO control register(25) - channel 2 (r/w): Clock prescaler select bit 0 */
NCO_CT_CH2_PRSC1 = 26, /**< NCO control register(26) - channel 2 (r/w): Clock prescaler select bit 1 */
NCO_CT_CH2_PRSC2 = 27, /**< NCO control register(27) - channel 2 (r/w): Clock prescaler select bit 2 */
NCO_CT_CH2_PULSE0 = 28, /**< NCO control register(28) - channel 2 (r/w): Pulse-mode: Pulse length select bit 0 */
NCO_CT_CH2_PULSE1 = 29, /**< NCO control register(29) - channel 2 (r/w): Pulse-mode: Pulse length select bit 1 */
NCO_CT_CH2_PULSE2 = 20 /**< NCO control register(30) - channel 2 (r/w): Pulse-mode: Pulse length select bit 2 */
/** TRNG control/data register bits */
enum NEORV32_TRNG_CT_enum {
TRNG_CT_DATA_LSB = 0, /**< TRNG data/control register(0) (r/-): Random data byte LSB */
TRNG_CT_DATA_MSB = 7, /**< TRNG data/control register(7) (r/-): Random data byte MSB */
 
TRNG_CT_EN = 30, /**< TRNG data/control register(30) (r/w): TRNG enable */
TRNG_CT_VALID = 31 /**< TRNG data/control register(31) (r/-): Random data output valid */
};
/**@}*/
 
/** Size of one "channel entry" in control register in bits */
#define NCO_CHX_WIDTH 10 // Size of one "channel entry" in control register in bits
 
/**********************************************************************//**
* @name IO Device: Watchdog Timer (WDT)
**************************************************************************/
/**@{*/
/** WDT base address */
#define WDT_BASE (0xFFFFFFBCUL) // /**< WDT base address */
/** WDT address space size in bytes */
#define WDT_SIZE (1*4) // /**< WDT address space size in bytes */
 
/** Watchdog control register (r/w) */
#define WDT_CT (*(IO_REG32 (WDT_BASE + 0)))
 
/** WTD control register bits */
enum NEORV32_WDT_CT_enum {
WDT_CT_EN = 0, /**< WDT control register(0) (r/w): Watchdog enable */
WDT_CT_CLK_SEL0 = 1, /**< WDT control register(1) (r/w): Clock prescaler select bit 0 */
WDT_CT_CLK_SEL1 = 2, /**< WDT control register(2) (r/w): Clock prescaler select bit 1 */
WDT_CT_CLK_SEL2 = 3, /**< WDT control register(3) (r/w): Clock prescaler select bit 2 */
WDT_CT_MODE = 4, /**< WDT control register(4) (r/w): Watchdog mode: 0=timeout causes interrupt, 1=timeout causes processor reset */
WDT_CT_RCAUSE = 5, /**< WDT control register(5) (r/-): Cause of last system reset: 0=external reset, 1=watchdog */
WDT_CT_RESET = 6, /**< WDT control register(6) (-/w): Reset WDT counter when set, auto-clears */
WDT_CT_FORCE = 7, /**< WDT control register(7) (-/w): Force WDT action, auto-clears */
WDT_CT_LOCK = 8 /**< WDT control register(8) (r/w): Lock write access to control register, clears on reset (HW or WDT) only */
};
/**@}*/
 
 
/**********************************************************************//**
* @name IO Device: General Purpose Input/Output Port Unit (GPIO)
**************************************************************************/
/**@{*/
/** GPIO base address */
#define GPIO_BASE (0xFFFFFFC0UL) // /**< GPIO base address */
/** GPIO address space size in bytes */
#define GPIO_SIZE (4*4) // /**< GPIO address space size in bytes */
 
/** GPIO parallel input port lower 32-bit (r/-) */
#define GPIO_INPUT_LO (*(IO_REG32 (GPIO_BASE + 0)))
/** GPIO parallel input port upper 32-bit (r/-) */
#define GPIO_INPUT_HI (*(IO_REG32 (GPIO_BASE + 4)))
/** GPIO parallel output port lower 32-bit (r/w) */
#define GPIO_OUTPUT_LO (*(IO_REG32 (GPIO_BASE + 8)))
/** GPIO parallel output port upper 32-bit (r/w) */
#define GPIO_OUTPUT_HI (*(IO_REG32 (GPIO_BASE + 12)))
 
/** GPIO parallel input 64-bit access (r/-) */
#define GPIO_INPUT (*(IO_REG64 (&GPIO_INPUT_LO)))
/** GPIO parallel output 64-bit access (r/w) */
#define GPIO_OUTPUT (*(IO_REG64 (&GPIO_OUTPUT_LO)))
/**@}*/
 
 
/**********************************************************************//**
* @name IO Device: Smart LED Hardware Interface (NEOLED)
**************************************************************************/
/**@{*/
1153,13 → 1105,12
* SYSINFO_FEATURES (r/-): Implemented processor devices/features
**************************************************************************/
enum NEORV32_SYSINFO_FEATURES_enum {
SYSINFO_FEATURES_BOOTLOADER = 0, /**< SYSINFO_FEATURES (0) (r/-): Bootloader implemented when 1 (via BOOTLOADER_EN generic) */
SYSINFO_FEATURES_BOOTLOADER = 0, /**< SYSINFO_FEATURES (0) (r/-): Bootloader implemented when 1 (via INT_BOOTLOADER_EN generic) */
SYSINFO_FEATURES_MEM_EXT = 1, /**< SYSINFO_FEATURES (1) (r/-): External bus interface implemented when 1 (via MEM_EXT_EN generic) */
SYSINFO_FEATURES_MEM_INT_IMEM = 2, /**< SYSINFO_FEATURES (2) (r/-): Processor-internal instruction memory implemented when 1 (via MEM_INT_IMEM_EN generic) */
SYSINFO_FEATURES_MEM_INT_IMEM_ROM = 3, /**< SYSINFO_FEATURES (3) (r/-): Processor-internal instruction memory implemented as ROM when 1 (via MEM_INT_IMEM_ROM generic) */
SYSINFO_FEATURES_MEM_INT_DMEM = 4, /**< SYSINFO_FEATURES (4) (r/-): Processor-internal data memory implemented when 1 (via MEM_INT_DMEM_EN generic) */
SYSINFO_FEATURES_MEM_EXT_ENDIAN = 5, /**< SYSINFO_FEATURES (5) (r/-): External bus interface uses BIG-endian byte-order when 1 (via package.xbus_big_endian_c constant) */
SYSINFO_FEATURES_ICACHE = 6, /**< SYSINFO_FEATURES (6) (r/-): Processor-internal instruction cache implemented when 1 (via ICACHE_EN generic) */
SYSINFO_FEATURES_MEM_INT_DMEM = 3, /**< SYSINFO_FEATURES (3) (r/-): Processor-internal data memory implemented when 1 (via MEM_INT_DMEM_EN generic) */
SYSINFO_FEATURES_MEM_EXT_ENDIAN = 4, /**< SYSINFO_FEATURES (4) (r/-): External bus interface uses BIG-endian byte-order when 1 (via package.xbus_big_endian_c constant) */
SYSINFO_FEATURES_ICACHE = 5, /**< SYSINFO_FEATURES (5) (r/-): Processor-internal instruction cache implemented when 1 (via ICACHE_EN generic) */
 
SYSINFO_FEATURES_OCD = 14, /**< SYSINFO_FEATURES (14) (r/-): On-chip debugger implemented when 1 (via ON_CHIP_DEBUGGER_EN generic) */
SYSINFO_FEATURES_HW_RESET = 15, /**< SYSINFO_FEATURES (15) (r/-): Dedicated hardware reset of core registers implemented when 1 (via package's dedicated_reset_c constant) */
1173,9 → 1124,10
SYSINFO_FEATURES_IO_WDT = 22, /**< SYSINFO_FEATURES (22) (r/-): Watchdog timer implemented when 1 (via IO_WDT_EN generic) */
SYSINFO_FEATURES_IO_CFS = 23, /**< SYSINFO_FEATURES (23) (r/-): Custom functions subsystem implemented when 1 (via IO_CFS_EN generic) */
SYSINFO_FEATURES_IO_TRNG = 24, /**< SYSINFO_FEATURES (24) (r/-): True random number generator implemented when 1 (via IO_TRNG_EN generic) */
SYSINFO_FEATURES_IO_NCO = 25, /**< SYSINFO_FEATURES (25) (r/-): Numerically-controlled oscillator implemented when 1 (via IO_NCO_EN generic) */
SYSINFO_FEATURES_IO_SLINK = 25, /**< SYSINFO_FEATURES (25) (r/-): Stream link interface implemented when 1 (via SLINK_NUM_RX & SLINK_NUM_TX generics) */
SYSINFO_FEATURES_IO_UART1 = 26, /**< SYSINFO_FEATURES (26) (r/-): Secondary universal asynchronous receiver/transmitter 1 implemented when 1 (via IO_UART1_EN generic) */
SYSINFO_FEATURES_IO_NEOLED = 27 /**< SYSINFO_FEATURES (27) (r/-): NeoPixel-compatible smart LED interface implemented when 1 (via IO_NEOLED_EN generic) */
SYSINFO_FEATURES_IO_NEOLED = 27, /**< SYSINFO_FEATURES (27) (r/-): NeoPixel-compatible smart LED interface implemented when 1 (via IO_NEOLED_EN generic) */
SYSINFO_FEATURES_IO_XIRQ = 28 /**< SYSINFO_FEATURES (28) (r/-): External interrupt controller implemented when 1 (via XIRQ_NUM_IO generic) */
};
 
/**********************************************************************//**
1220,13 → 1172,19
#include "neorv32_cfs.h"
#include "neorv32_gpio.h"
#include "neorv32_mtime.h"
#include "neorv32_nco.h"
#include "neorv32_neoled.h"
#include "neorv32_pwm.h"
#include "neorv32_slink.h"
#include "neorv32_spi.h"
#include "neorv32_trng.h"
#include "neorv32_twi.h"
#include "neorv32_uart.h"
#include "neorv32_wdt.h"
#include "neorv32_xirq.h"
 
 
#ifdef __cplusplus
}
#endif
 
#endif // neorv32_h
/lib/include/neorv32_cpu.h
61,6 → 61,15
 
 
/**********************************************************************//**
* Prototype for "after-main handler". This function is called if main() returns.
*
* @param[in] return_code Return value of main() function.
* @return Return value is irrelevant (there is no one left to check for it...).
**************************************************************************/
extern int __neorv32_crt0_after_main(int32_t return_code);
 
 
/**********************************************************************//**
* Store unsigned word to address space.
*
* @note An unaligned access address will raise an alignment exception.
/lib/include/neorv32_gpio.h
45,13 → 45,13
#define neorv32_gpio_h
 
// prototypes
int neorv32_gpio_available(void);
void neorv32_gpio_pin_set(uint8_t p);
void neorv32_gpio_pin_clr(uint8_t p);
void neorv32_gpio_pin_toggle(uint8_t p);
uint32_t neorv32_gpio_pin_get(uint8_t p);
void neorv32_gpio_port_set(uint32_t d);
uint32_t neorv32_gpio_port_get(void);
void neorv32_gpio_pin_change_config(uint32_t pin_sel);
int neorv32_gpio_available(void);
void neorv32_gpio_pin_set(int pin);
void neorv32_gpio_pin_clr(int pin);
void neorv32_gpio_pin_toggle(int pin);
uint32_t neorv32_gpio_pin_get(int pin);
 
void neorv32_gpio_port_set(uint64_t d);
uint64_t neorv32_gpio_port_get(void);
 
#endif // neorv32_gpio_h
/lib/include/neorv32_intrinsics.h
148,19 → 148,19
 
//** Construct custom R3-type instruction (4 registers, funct3, opcode) */
#define CUSTOM_INSTR_R3_TYPE(rs3, rs2, rs1, funct3, rd, opcode) \
asm volatile (".word "STR(CMD_WORD_R3_TYPE(GET_REG_ADDR(rs3), GET_REG_ADDR(rs2), GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
asm volatile (".word " STR(CMD_WORD_R3_TYPE(GET_REG_ADDR(rs3), GET_REG_ADDR(rs2), GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
 
//** Construct custom R2-type instruction (3 registers, funct3, funct7, opcode) */
#define CUSTOM_INSTR_R2_TYPE(funct7, rs2, rs1, funct3, rd, opcode) \
asm volatile (".word "STR(CMD_WORD_R2_TYPE(funct7, GET_REG_ADDR(rs2), GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
asm volatile (".word " STR(CMD_WORD_R2_TYPE(funct7, GET_REG_ADDR(rs2), GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
 
//** Construct custom R1-type instruction (2 registers, funct3, funct7, funct5, opcode) */
#define CUSTOM_INSTR_R1_TYPE(funct7, funct5, rs1, funct3, rd, opcode) \
asm volatile (".word "STR(CMD_WORD_R2_TYPE(funct7, funct5, GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
asm volatile (".word " STR(CMD_WORD_R2_TYPE(funct7, funct5, GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
//** Construct custom I-type instruction (2 registers, funct3, imm12, opcode) */
#define CUSTOM_INSTR_I_TYPE(imm12, rs1, funct3, rd, opcode) \
asm volatile (".word "STR(CMD_WORD_I_TYPE(imm12, GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
asm volatile (".word " STR(CMD_WORD_I_TYPE(imm12, GET_REG_ADDR(rs1), funct3, GET_REG_ADDR(rd), opcode))"\n");
/**@}*/
 
#endif // neorv32_intrinsics_h
/lib/include/neorv32_pwm.h
48,6 → 48,7
int neorv32_pwm_available(void);
void neorv32_pwm_setup(uint8_t prsc);
void neorv32_pwm_disable(void);
void neorv32_pwm_enable(void);
int neorv32_pmw_get_num_channels(void);
void neorv32_pwm_set(uint8_t channel, uint8_t duty);
uint8_t neorv32_pwm_get(uint8_t channel);
/lib/include/neorv32_slink.h
0,0 → 1,265
// #################################################################################################
// # << NEORV32: neorv32_slink.h - Stream Link Interface HW Driver >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_slink.h
* @author Stephan Nolting
* @brief Stream Link Interface HW driver header file.
**************************************************************************/
 
#ifndef neorv32_slink_h
#define neorv32_slink_h
 
// prototypes
int neorv32_slink_available(void);
void neorv32_slink_enable(void);
void neorv32_slink_disable(void);
int neorv32_slink_get_rx_num(void);
int neorv32_slink_get_tx_num(void);
int neorv32_slink_get_rx_depth(void);
int neorv32_slink_get_tx_depth(void);
// non-blocking transmit
int neorv32_slink_tx0_nonblocking(uint32_t tx_data);
int neorv32_slink_tx1_nonblocking(uint32_t tx_data);
int neorv32_slink_tx2_nonblocking(uint32_t tx_data);
int neorv32_slink_tx3_nonblocking(uint32_t tx_data);
int neorv32_slink_tx4_nonblocking(uint32_t tx_data);
int neorv32_slink_tx5_nonblocking(uint32_t tx_data);
int neorv32_slink_tx6_nonblocking(uint32_t tx_data);
int neorv32_slink_tx7_nonblocking(uint32_t tx_data);
// non-blocking receive
int neorv32_slink_rx0_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx1_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx2_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx3_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx4_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx5_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx6_nonblocking(uint32_t *rx_data);
int neorv32_slink_rx7_nonblocking(uint32_t *rx_data);
 
 
/**********************************************************************//**
* Write data to TX stream link 0 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx0_blocking(uint32_t tx_data) {
SLINK_CH0 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 1 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx1_blocking(uint32_t tx_data) {
SLINK_CH1 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 2 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx2_blocking(uint32_t tx_data) {
SLINK_CH2 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 3 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx3_blocking(uint32_t tx_data) {
SLINK_CH3 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 4 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx4_blocking(uint32_t tx_data) {
SLINK_CH4 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 5 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx5_blocking(uint32_t tx_data) {
SLINK_CH5 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 6 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx6_blocking(uint32_t tx_data) {
SLINK_CH6 = tx_data;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 7 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_tx7_blocking(uint32_t tx_data) {
SLINK_CH7 = tx_data;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 0 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx0_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH0;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 1 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx1_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 2 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx2_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH2;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 3 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx3_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH3;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 4 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx4_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH4;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 5 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx5_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH5;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 6 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx6_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH6;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 7 (blocking!)
*
* @warning This function will raise an exception when the bus access times out!
*
* @param[in,out] rx_data Pointer to return read data.
**************************************************************************/
inline void __attribute__ ((always_inline)) neorv32_slink_rx7_blocking(uint32_t *rx_data) {
*rx_data = SLINK_CH7;
}
 
 
#endif // neorv32_slink_h
/lib/include/neorv32_spi.h
48,6 → 48,7
int neorv32_spi_available(void);
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_polarity, uint8_t data_size);
void neorv32_spi_disable(void);
void neorv32_spi_enable(void);
void neorv32_spi_cs_en(uint8_t cs);
void neorv32_spi_cs_dis(uint8_t cs);
uint32_t neorv32_spi_trans(uint32_t tx_data);
/lib/include/neorv32_twi.h
48,6 → 48,7
int neorv32_twi_available(void);
void neorv32_twi_setup(uint8_t prsc, uint8_t ckst_en);
void neorv32_twi_disable(void);
void neorv32_twi_enable(void);
void neorv32_twi_mack_enable(void);
int neorv32_twi_busy(void);
int neorv32_twi_start_trans(uint8_t a);
/lib/include/neorv32_uart.h
53,6 → 53,7
int neorv32_uart_available(void);
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con);
void neorv32_uart_disable(void);
void neorv32_uart_enable(void);
void neorv32_uart_putc(char c);
int neorv32_uart_tx_busy(void);
char neorv32_uart_getc(void);
67,6 → 68,7
int neorv32_uart0_available(void);
void neorv32_uart0_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con);
void neorv32_uart0_disable(void);
void neorv32_uart0_enable(void);
void neorv32_uart0_putc(char c);
int neorv32_uart0_tx_busy(void);
char neorv32_uart0_getc(void);
81,6 → 83,7
int neorv32_uart1_available(void);
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con);
void neorv32_uart1_disable(void);
void neorv32_uart1_enable(void);
void neorv32_uart1_putc(char c);
int neorv32_uart1_tx_busy(void);
char neorv32_uart1_getc(void);
/lib/include/neorv32_xirq.h
0,0 → 1,70
// #################################################################################################
// # << NEORV32: neorv32_xirq.h - External Interrupt controller HW Driver >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_xirq.h
* @author Stephan Nolting
* @brief SExternal Interrupt controller HW driver header file.
**************************************************************************/
 
#ifndef neorv32_xirq_h
#define neorv32_xirq_h
 
 
/**********************************************************************//**
* @name XIRQ fast interrupt channel
**************************************************************************/
/**@{*/
/** XIRQ MIE FIRQ bit */
#define XIRQ_FIRQ_ENABLE CSR_MIE_FIRQ8E // MIE FIRQ bit
/** XIRQ MIP FIRQ bit */
#define XIRQ_FIRQ_PENDING CSR_MIP_FIRQ8P // MIP FIRQ bit
/** XIRQ RTE IRQ ID */
#define XIRQ_RTE_ID RTE_TRAP_FIRQ_8 // RTE IRQ ID
/**@}*/
 
 
// prototypes
int neorv32_xirq_available(void);
int neorv32_xirq_setup(void);
void neorv32_xirq_global_enable(void);
void neorv32_xirq_global_disable(void);
int neorv32_xirq_get_num(void);
 
int neorv32_xirq_install(uint8_t ch, void (*handler)(void));
int neorv32_xirq_uninstall(uint8_t ch);
 
 
#endif // neorv32_xirq_h
/lib/source/neorv32_cpu.c
685,7 → 685,7
}
 
// inhibt auto-update
asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTEREN_HPM3));
asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_HPM3));
 
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 0xffffffff);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff);
/lib/source/neorv32_gpio.c
64,12 → 64,18
/**********************************************************************//**
* Set single pin of GPIO's output port.
*
* @param[in] pin Output pin number to be set (0..31).
* @param[in] pin Output pin number to be set (0..63).
**************************************************************************/
void neorv32_gpio_pin_set(uint8_t pin) {
void neorv32_gpio_pin_set(int pin) {
 
pin &= 0x1f;
GPIO_OUTPUT = GPIO_OUTPUT | (uint32_t)(1 << pin);
uint32_t mask = (uint32_t)(1 << (pin & 0x1f));
 
if (pin < 32) {
GPIO_OUTPUT_LO |= mask;
}
else {
GPIO_OUTPUT_HI |= mask;
}
}
 
 
76,12 → 82,18
/**********************************************************************//**
* Clear single pin of GPIO's output port.
*
* @param[in] pin Output pin number to be cleared (0..31).
* @param[in] pin Output pin number to be cleared (0..63).
**************************************************************************/
void neorv32_gpio_pin_clr(uint8_t pin) {
void neorv32_gpio_pin_clr(int pin) {
 
pin &= 0x1f;
GPIO_OUTPUT = GPIO_OUTPUT & ~((uint32_t)(1 << pin));
uint32_t mask = (uint32_t)(1 << (pin & 0x1f));
 
if (pin < 32) {
GPIO_OUTPUT_LO &= ~mask;
}
else {
GPIO_OUTPUT_HI &= ~mask;
}
}
 
 
88,12 → 100,18
/**********************************************************************//**
* Toggle single pin of GPIO's output port.
*
* @param[in] pin Output pin number to be toggled (0..31).
* @param[in] pin Output pin number to be toggled (0..63).
**************************************************************************/
void neorv32_gpio_pin_toggle(uint8_t pin) {
void neorv32_gpio_pin_toggle(int pin) {
 
pin &= 0x1f;
GPIO_OUTPUT = GPIO_OUTPUT ^ (uint32_t)(1 << pin);
uint32_t mask = (uint32_t)(1 << (pin & 0x1f));
 
if (pin < 32) {
GPIO_OUTPUT_LO ^= mask;
}
else {
GPIO_OUTPUT_HI ^= mask;
}
}
 
 
100,13 → 118,19
/**********************************************************************//**
* Get single pin of GPIO's input port.
*
* @param[in] pin Input pin to be read (0..31).
* @return uint32_t: =0 if pin is low, !=0 if pin is high.
* @param[in] pin Input pin to be read (0..63).
* @return =0 if pin is low, !=0 if pin is high.
**************************************************************************/
uint32_t neorv32_gpio_pin_get(uint8_t pin) {
uint32_t neorv32_gpio_pin_get(int pin) {
 
pin &= 0x1f;
return GPIO_INPUT & (uint32_t)(1 << pin);
uint32_t mask = (uint32_t)(1 << (pin & 0x1f));
 
if (pin < 32) {
return GPIO_INPUT_LO & mask;
}
else {
return GPIO_INPUT_HI & mask;
}
}
 
 
113,9 → 137,9
/**********************************************************************//**
* Set complete GPIO output port.
*
* @param[in] port_data New output port value (32-bit).
* @param[in] port_data New output port value (64-bit).
**************************************************************************/
void neorv32_gpio_port_set(uint32_t port_data) {
void neorv32_gpio_port_set(uint64_t port_data) {
 
GPIO_OUTPUT = port_data;
}
124,23 → 148,10
/**********************************************************************//**
* Get complete GPIO input port.
*
* @return Current input port state (32-bit).
* @return Current input port state (64-bit).
**************************************************************************/
uint32_t neorv32_gpio_port_get(void) {
uint64_t neorv32_gpio_port_get(void) {
 
return GPIO_INPUT;
}
 
 
/**********************************************************************//**
* Configure pin-change IRQ mask for input pins.
*
* @note The pin-change IRQ will trigger on any transition (rising and falling edge) for any enabled input pin.
*
* @param[in] pin_sel Mask to select which input pins can cause a pin-change IRQ (32-bit), 1 = pin enabled.
**************************************************************************/
void neorv32_gpio_pin_change_config(uint32_t pin_sel) {
 
GPIO_INPUT = pin_sel;
}
 
/lib/source/neorv32_pwm.c
90,6 → 90,15
 
 
/**********************************************************************//**
* Enable pulse width modulation controller.
**************************************************************************/
void neorv32_pwm_enable(void) {
 
PWM_CT |= ((uint32_t)(1 << PWM_CT_EN));
}
 
 
/**********************************************************************//**
* Get number of implemented channels.
* @warning This function will override all duty cycle configuration registers.
*
/lib/source/neorv32_rte.c
63,11 → 63,6
**************************************************************************/
void neorv32_rte_setup(void) {
 
// check if CSR system is available at all
if (neorv32_cpu_csr_read(CSR_MISA) == 0) {
neorv32_uart_print("<RTE> WARNING! CPU CSR system not available! </RTE>");
}
 
// configure trap handler base address
uint32_t mtvec_base = (uint32_t)(&__neorv32_rte_core);
neorv32_cpu_csr_write(CSR_MTVEC, mtvec_base);
137,7 → 132,7
register uint32_t rte_mcause = neorv32_cpu_csr_read(CSR_MCAUSE);
 
// compute return address
if ((rte_mcause & 0x80000000) == 0) { // modify pc only if exception
if (((int32_t)rte_mcause) >= 0) { // modify pc only if exception (MSB cleared)
 
// get low half word of faulting instruction
register uint32_t rte_trap_inst;
203,6 → 198,10
**************************************************************************/
static void __neorv32_rte_debug_exc_handler(void) {
 
if (neorv32_uart0_available() == 0) {
return; // handler cannot output anything if UART0 is not implemented
}
 
char tmp;
 
// intro
266,6 → 265,10
**************************************************************************/
void neorv32_rte_print_hw_config(void) {
 
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
 
uint32_t tmp;
int i;
char c;
273,50 → 276,57
neorv32_uart_printf("\n\n<<< Processor Configuration Overview >>>\n");
 
// Processor - general stuff
neorv32_uart_printf("\n=== << General >> ===\n");
neorv32_uart_printf("Clock: %u Hz\n", SYSINFO_CLK);
neorv32_uart_printf("User ID: 0x%x\n", SYSINFO_USER_CODE);
neorv32_uart_printf("Full HW reset: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_HW_RESET));
neorv32_uart_printf("On-chip debug: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_OCD));
neorv32_uart0_printf("\n=== << General >> ===\n"
"Clock: %u Hz\n"
"User ID: 0x%x\n", SYSINFO_CLK, SYSINFO_USER_CODE);
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_HW_RESET));
neorv32_uart0_printf("Boot Config.: Boot ");
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER)) {
neorv32_uart0_printf("via Bootloader\n");
}
else {
neorv32_uart0_printf("from memory (@ 0x%x)\n", SYSINFO_ISPACE_BASE);
}
neorv32_uart0_printf("On-chip debug: "); __neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_OCD));
 
 
// CPU configuration
neorv32_uart_printf("\n=== << CPU >> ===\n");
neorv32_uart0_printf("\n=== << CPU >> ===\n");
 
// ID
neorv32_uart_printf("Hart ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID));
neorv32_uart_printf("Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MVENDORID));
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));
 
tmp = neorv32_cpu_csr_read(CSR_MARCHID);
neorv32_uart_printf("Architecture ID: 0x%x", tmp);
neorv32_uart0_printf("Architecture ID: 0x%x", tmp);
if (tmp == NEORV32_ARCHID) {
neorv32_uart_printf(" (NEORV32)");
neorv32_uart0_printf(" (NEORV32)");
}
 
// hardware version
neorv32_uart_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
neorv32_uart0_printf("\nImplementation ID: 0x%x (", neorv32_cpu_csr_read(CSR_MIMPID));
neorv32_rte_print_hw_version();
neorv32_uart_putc(')');
neorv32_uart0_putc(')');
 
// CPU architecture and endianness
neorv32_uart_printf("\nArchitecture: ");
neorv32_uart0_printf("\nArchitecture: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
tmp = (tmp >> 30) & 0x03;
if (tmp == 1) {
neorv32_uart_printf("rv32-little");
neorv32_uart0_printf("rv32-little");
}
else {
neorv32_uart_printf("unknown");
neorv32_uart0_printf("unknown");
}
// CPU extensions
neorv32_uart_printf("\nExtensions: ");
neorv32_uart0_printf("\nISA extensions: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
for (i=0; i<26; i++) {
if (tmp & (1 << i)) {
c = (char)('A' + i);
neorv32_uart_putc(c);
neorv32_uart_putc(' ');
neorv32_uart0_putc(c);
neorv32_uart0_putc(' ');
}
}
323,68 → 333,67
// Z* CPU extensions (from custom "mzext" CSR)
tmp = neorv32_cpu_csr_read(CSR_MZEXT);
if (tmp & (1<<CSR_MZEXT_ZICSR)) {
neorv32_uart_printf("Zicsr ");
neorv32_uart0_printf("Zicsr ");
}
if (tmp & (1<<CSR_MZEXT_ZIFENCEI)) {
neorv32_uart_printf("Zifencei ");
neorv32_uart0_printf("Zifencei ");
}
if (tmp & (1<<CSR_MZEXT_ZMMUL)) {
neorv32_uart0_printf("Zmmul ");
}
 
if (tmp & (1<<CSR_MZEXT_ZFINX)) {
neorv32_uart_printf("Zfinx ");
neorv32_uart0_printf("Zfinx ");
}
if (tmp & (1<<CSR_MZEXT_ZXNOCNT)) {
neorv32_uart_printf("Zxnocnt(!) ");
neorv32_uart0_printf("Zxnocnt(!) ");
}
if (tmp & (1<<CSR_MZEXT_ZXSCNT)) {
neorv32_uart_printf("Zxscnt(!) ");
neorv32_uart0_printf("Zxscnt(!) ");
}
if (tmp & (1<<CSR_MZEXT_DEBUGMODE)) {
neorv32_uart_printf("Debug-Mode ");
neorv32_uart0_printf("Debug-Mode ");
}
 
// check physical memory protection
neorv32_uart_printf("\nPMP: ");
neorv32_uart0_printf("\nPMP: ");
uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
if (pmp_num_regions != 0) {
neorv32_uart_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
}
else {
neorv32_uart_printf("not implemented\n");
neorv32_uart0_printf("not implemented\n");
}
 
// check hardware performance monitors
neorv32_uart_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
neorv32_uart_printf("\n=== << Memory Configuration >> ===\n");
neorv32_uart0_printf("\n=== << Memory Configuration >> ===\n");
 
neorv32_uart_printf("Instr. base address: 0x%x\n", SYSINFO_ISPACE_BASE);
neorv32_uart0_printf("Instr. base address: 0x%x\n", SYSINFO_ISPACE_BASE);
 
// IMEM
neorv32_uart_printf("Internal IMEM: ");
neorv32_uart0_printf("Internal IMEM: ");
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)) {
neorv32_uart_printf("yes, %u bytes", SYSINFO_IMEM_SIZE);
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) {
neorv32_uart_printf(", read-only (ROM)");
}
neorv32_uart0_printf("yes, %u bytes\n", SYSINFO_IMEM_SIZE);
}
else {
neorv32_uart_printf("no");
neorv32_uart0_printf("no\n");
}
neorv32_uart_printf("\n");
 
// DMEM
neorv32_uart_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE);
neorv32_uart_printf("Internal DMEM: ");
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)) { neorv32_uart_printf("yes, %u bytes\n", SYSINFO_DMEM_SIZE); }
else { neorv32_uart_printf("no\n"); }
neorv32_uart0_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE);
neorv32_uart0_printf("Internal DMEM: ");
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)) { neorv32_uart0_printf("yes, %u bytes\n", SYSINFO_DMEM_SIZE); }
else { neorv32_uart0_printf("no\n"); }
 
// i-cache
neorv32_uart_printf("Internal i-cache: ");
neorv32_uart0_printf("Internal i-cache: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE));
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) {
neorv32_uart_printf("- ");
neorv32_uart0_printf("- ");
 
uint32_t ic_block_size = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
if (ic_block_size) {
405,71 → 414,45
uint32_t ic_associativity = (SYSINFO_CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
ic_associativity = 1 << ic_associativity;
 
neorv32_uart_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) {
neorv32_uart_printf(" (direct-mapped)\n");
neorv32_uart0_printf(" (direct-mapped)\n");
}
else if (((SYSINFO_CACHE >> SYSINFO_CACHE_IC_REPLACEMENT_0) & 0x0F) == 1) {
neorv32_uart_printf(" (LRU replacement policy)\n");
neorv32_uart0_printf(" (LRU replacement policy)\n");
}
else {
neorv32_uart_printf("\n");
neorv32_uart0_printf("\n");
}
}
 
neorv32_uart_printf("Bootloader: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER));
 
neorv32_uart_printf("Ext. bus interface: ");
neorv32_uart0_printf("Ext. bus interface: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT));
neorv32_uart_printf("Ext. bus Endianness: ");
neorv32_uart0_printf("Ext. bus Endianness: ");
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) {
neorv32_uart_printf("big\n");
neorv32_uart0_printf("big\n");
}
else {
neorv32_uart_printf("little\n");
neorv32_uart0_printf("little\n");
}
 
// peripherals
neorv32_uart_printf("\n=== << Peripherals >> ===\n");
neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
 
tmp = SYSINFO_FEATURES;
 
neorv32_uart_printf("GPIO - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO));
 
neorv32_uart_printf("MTIME - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME));
 
neorv32_uart_printf("UART0 - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART0));
 
neorv32_uart_printf("UART1 - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART1));
 
neorv32_uart_printf("SPI - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI));
 
neorv32_uart_printf("TWI - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI));
 
neorv32_uart_printf("PWM - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM));
 
neorv32_uart_printf("WDT - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT));
 
neorv32_uart_printf("TRNG - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
 
neorv32_uart_printf("CFS - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFS));
 
neorv32_uart_printf("NCO - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NCO));
 
neorv32_uart_printf("NEOLED - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NEOLED));
neorv32_uart0_printf("GPIO - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_GPIO));
neorv32_uart0_printf("MTIME - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_MTIME));
neorv32_uart0_printf("UART0 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART0));
neorv32_uart0_printf("UART1 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_UART1));
neorv32_uart0_printf("SPI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SPI));
neorv32_uart0_printf("TWI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TWI));
neorv32_uart0_printf("PWM - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_PWM));
neorv32_uart0_printf("WDT - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_WDT));
neorv32_uart0_printf("TRNG - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
neorv32_uart0_printf("CFS - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFS));
neorv32_uart0_printf("SLINK - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_SLINK));
neorv32_uart0_printf("NEOLED - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_NEOLED));
neorv32_uart0_printf("XIRQ - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_XIRQ));
}
 
 
482,10 → 465,10
static void __neorv32_rte_print_true_false(int state) {
 
if (state) {
neorv32_uart_print("yes\n");
neorv32_uart0_print("yes\n");
}
else {
neorv32_uart_print("no\n");
neorv32_uart0_print("no\n");
}
}
 
500,12 → 483,12
 
static const char hex_symbols[16] = "0123456789ABCDEF";
 
neorv32_uart_print("0x");
neorv32_uart0_print("0x");
 
int i;
for (i=0; i<8; i++) {
uint32_t index = (num >> (28 - 4*i)) & 0xF;
neorv32_uart_putc(hex_symbols[index]);
neorv32_uart0_putc(hex_symbols[index]);
}
}
 
518,6 → 501,10
uint32_t i;
char tmp, cnt;
 
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
 
for (i=0; i<4; i++) {
 
tmp = (char)(neorv32_cpu_csr_read(CSR_MIMPID) >> (24 - 8*i));
530,11 → 517,11
}
 
if (cnt) {
neorv32_uart_putc('0' + cnt);
neorv32_uart0_putc('0' + cnt);
}
neorv32_uart_putc('0' + tmp);
neorv32_uart0_putc('0' + tmp);
if (i < 3) {
neorv32_uart_putc('.');
neorv32_uart0_putc('.');
}
}
}
545,10 → 532,14
**************************************************************************/
void neorv32_rte_print_credits(void) {
 
neorv32_uart_print("The NEORV32 Processor Project\n"
"Copyright 2021, Stephan Nolting\n"
"BSD 3-Clause License\n"
"https://github.com/stnolting/neorv32\n\n");
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
 
neorv32_uart0_print("The NEORV32 RISC-V Processor\n"
"(c) Stephan Nolting\n"
"BSD 3-Clause License\n"
"https://github.com/stnolting/neorv32\n\n");
}
 
 
575,22 → 566,26
int u,v,w;
uint32_t tmp;
 
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
 
for (u=0; u<11; u++) {
neorv32_uart_print("\n");
neorv32_uart0_print("\n");
for (v=0; v<4; v++) {
tmp = logo_data_c[u][v];
for (w=0; w<32; w++){
if (tmp & 0x80000000UL) { // check MSB
neorv32_uart_putc('#');
if (((int32_t)tmp) < 0) { // check MSB
neorv32_uart0_putc('#');
}
else {
neorv32_uart_putc(' ');
neorv32_uart0_putc(' ');
}
tmp <<= 1;
}
}
}
neorv32_uart_print("\n");
neorv32_uart0_print("\n");
}
 
 
599,6 → 594,10
**************************************************************************/
void neorv32_rte_print_license(void) {
 
if (neorv32_uart0_available() == 0) {
return; // cannot output anything if UART0 is not implemented
}
 
neorv32_uart_print(
"\n"
"BSD 3-Clause License\n"
644,41 → 643,41
uint32_t misa_cc = 0;
 
#if defined __riscv_atomic || defined __riscv_a
misa_cc |= 1 << CSR_MISA_A_EXT;
misa_cc |= 1 << CSR_MISA_A;
#endif
 
#ifdef __riscv_b
misa_cc |= 1 << CSR_MISA_B_EXT;
misa_cc |= 1 << CSR_MISA_B;
#endif
 
#if defined __riscv_compressed || defined __riscv_c
misa_cc |= 1 << CSR_MISA_C_EXT;
misa_cc |= 1 << CSR_MISA_C;
#endif
 
#if (__riscv_flen == 64) || defined __riscv_d
misa_cc |= 1 << CSR_MISA_D_EXT;
misa_cc |= 1 << CSR_MISA_D;
#endif
 
#ifdef __riscv_32e
misa_cc |= 1 << CSR_MISA_E_EXT;
misa_cc |= 1 << CSR_MISA_E;
#else
misa_cc |= 1 << CSR_MISA_I_EXT;
misa_cc |= 1 << CSR_MISA_I;
#endif
 
#if (__riscv_flen == 32) || defined __riscv_f
misa_cc |= 1 << CSR_MISA_F_EXT;
misa_cc |= 1 << CSR_MISA_F;
#endif
 
#if defined __riscv_mul || defined __riscv_m
misa_cc |= 1 << CSR_MISA_M_EXT;
misa_cc |= 1 << CSR_MISA_M;
#endif
 
#if (__riscv_xlen == 32)
misa_cc |= 1 << CSR_MISA_MXL_LO_EXT;
misa_cc |= 1 << CSR_MISA_MXL_LO;
#elif (__riscv_xlen == 64)
misa_cc |= 2 << CSR_MISA_MXL_LO_EXT;
misa_cc |= 2 << CSR_MISA_MXL_LO;
#else
misa_cc |= 3 << CSR_MISA_MXL_LO_EXT;
misa_cc |= 3 << CSR_MISA_MXL_LO;
#endif
 
return misa_cc;
704,7 → 703,7
return 0;
}
else {
if (silent == 0) {
if ((silent == 0) || (neorv32_uart0_available() == 0)) {
neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
"SW_ISA = 0x%x (compiler flags)\n"
"HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
/lib/source/neorv32_slink.c
0,0 → 1,401
// #################################################################################################
// # << NEORV32: neorv32_slink.c - Stream Link Interface HW Driver >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_slink.h
* @author Stephan Nolting
* @brief Stream Link Interface HW driver source file.
**************************************************************************/
 
#include "neorv32.h"
#include "neorv32_slink.h"
 
 
/**********************************************************************//**
* Check if stream link interface was synthesized.
*
* @return 0 if SLINK was not synthesized, 1 if SLINK is available.
**************************************************************************/
int neorv32_slink_available(void) {
 
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_SLINK)) {
return 1;
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Activate stream link interface.
**************************************************************************/
void neorv32_slink_enable(void) {
 
SLINK_CT |= (uint32_t)(1 << SLINK_CT_EN);
}
 
 
/**********************************************************************//**
* Deactivate stream link interface.
*
* @note This will also clear all link FIFOs.
**************************************************************************/
void neorv32_slink_disable(void) {
 
SLINK_CT &= ~(uint32_t)(1 << SLINK_CT_EN);
}
 
 
/**********************************************************************//**
* Get number of implemented RX links
*
* @return Number of implemented RX link (0..8).
**************************************************************************/
int neorv32_slink_get_rx_num(void) {
 
if (neorv32_slink_available()) {
return (int)(((SLINK_CT >> SLINK_CT_RX_NUM0) & 0x07) + 1);
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Get number of implemented TX links
*
* @return Number of implemented TX link (0..8).
**************************************************************************/
int neorv32_slink_get_tx_num(void) {
 
if (neorv32_slink_available()) {
return (int)(((SLINK_CT >> SLINK_CT_TX_NUM0) & 0x07) + 1);
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Get FIFO depth of RX links
*
* @return FIFO depth of RX links (1..32768); 0 if no RX links implemented.
**************************************************************************/
int neorv32_slink_get_rx_depth(void) {
 
if (neorv32_slink_available()) {
uint32_t tmp = (SLINK_CT >> SLINK_CT_RX_FIFO_S0) & 0x0f;
return (int)(1 << tmp);
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Get FIFO depth of TX links
*
* @return FIFO depth of TX links (1..32768); 0 if no TX links implemented.
**************************************************************************/
int neorv32_slink_get_tx_depth(void) {
 
if (neorv32_slink_available()) {
uint32_t tmp = (SLINK_CT >> SLINK_CT_TX_FIFO_S0) & 0x0f;
return (int)(1 << tmp);
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Write data to TX stream link 0 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx0_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX0_FREE)) {
SLINK_CH0 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 1 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx1_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX1_FREE)) {
SLINK_CH1 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 2 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx2_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX2_FREE)) {
SLINK_CH2 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 3 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx3_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX3_FREE)) {
SLINK_CH3 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 4 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx4_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX4_FREE)) {
SLINK_CH4 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 5 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx5_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX5_FREE)) {
SLINK_CH5 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 6 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx6_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX6_FREE)) {
SLINK_CH6 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Write data to TX stream link 7 (non-blocking)
*
* @param[in] tx_data Data to send to link.
* @return 0 if data was send, 1 if link is still busy.
**************************************************************************/
int neorv32_slink_tx7_nonblocking(uint32_t tx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_TX7_FREE)) {
SLINK_CH7 = tx_data;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 0 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx0_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX0_AVAIL)) {
*rx_data = SLINK_CH0;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 1 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx1_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX1_AVAIL)) {
*rx_data = SLINK_CH1;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 2 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx2_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX2_AVAIL)) {
*rx_data = SLINK_CH2;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 3 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx3_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX3_AVAIL)) {
*rx_data = SLINK_CH3;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 4 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx4_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX4_AVAIL)) {
*rx_data = SLINK_CH4;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 5 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx5_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX5_AVAIL)) {
*rx_data = SLINK_CH5;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 6 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx6_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX6_AVAIL)) {
*rx_data = SLINK_CH6;
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Read data from RX stream link 7 (non-blocking)
*
* @param[in,out] rx_data Pointer to return read data. Only valid if function return value = 0.
* @return 0 if data was received, 1 if there is no data to fetch.
**************************************************************************/
int neorv32_slink_rx7_nonblocking(uint32_t *rx_data) {
 
if (SLINK_CT & (1 << SLINK_CT_RX7_AVAIL)) {
*rx_data = SLINK_CH7;
return 0;
}
return 1;
}
/lib/source/neorv32_spi.c
98,6 → 98,15
 
 
/**********************************************************************//**
* Enable SPI controller.
**************************************************************************/
void neorv32_spi_enable(void) {
 
SPI_CT |= ((uint32_t)(1 << SPI_CT_EN));
}
 
 
/**********************************************************************//**
* Activate SPI chip select signal.
*
* @note The chip select output lines are LOW when activated.
/lib/source/neorv32_twi.c
94,6 → 94,15
 
 
/**********************************************************************//**
* Enable TWI controller.
**************************************************************************/
void neorv32_twi_enable(void) {
 
TWI_CT |= (uint32_t)(1 << TWI_CT_EN);
}
 
 
/**********************************************************************//**
* Activate sending ACKs by controller (MACK).
**************************************************************************/
void neorv32_twi_mack_enable(void) {
/lib/source/neorv32_uart.c
46,6 → 46,7
#include "neorv32.h"
#include "neorv32_uart.h"
#include <string.h>
#include <stdarg.h>
 
/// \cond
// Private functions
94,6 → 95,13
 
 
/**********************************************************************//**
* Enable UART0.
* @warning This functions maps to UART0 (primary UART).
**************************************************************************/
void neorv32_uart_enable(void) { neorv32_uart0_enable(); }
 
 
/**********************************************************************//**
* Send single char via UART0.
*
* @warning This functions maps to UART0 (primary UART).
310,6 → 318,15
 
 
/**********************************************************************//**
* Enable UART0.
**************************************************************************/
void neorv32_uart0_enable(void) {
 
UART0_CT = ((uint32_t)(1 << UART_CT_EN));
}
 
 
/**********************************************************************//**
* Send single char via UART0.
*
* @note This function is blocking.
318,13 → 335,9
**************************************************************************/
void neorv32_uart0_putc(char c) {
 
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
UART0_DATA = ((uint32_t)c) << UART_DATA_LSB;
#else
// wait for previous transfer to finish
while ((UART0_CT & (1<<UART_CT_TX_BUSY)) != 0);
UART0_DATA = ((uint32_t)c) << UART_DATA_LSB;
#endif
}
 
 
665,6 → 678,15
 
 
/**********************************************************************//**
* Enable UART1.
**************************************************************************/
void neorv32_uart1_enable(void) {
 
UART1_CT |= ((uint32_t)(1 << UART_CT_EN));
}
 
 
/**********************************************************************//**
* Send single char via UART1.
*
* @note This function is blocking.
673,13 → 695,9
**************************************************************************/
void neorv32_uart1_putc(char c) {
 
#ifdef UART1_SIM_MODE
UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
#else
// wait for previous transfer to finish
while ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0);
UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
#endif
}
 
 
/lib/source/neorv32_wdt.c
64,9 → 64,9
/**********************************************************************//**
* Configure and enable watchdog timer. The WDT control register bits are listed in #NEORV32_WDT_CT_enum.
*
* @param[in] prsc Clock prescaler to selet timeout interval. See #NEORV32_CLOCK_PRSC_enum.
* @param[in] prsc Clock prescaler to select timeout interval. See #NEORV32_CLOCK_PRSC_enum.
* @param[in] mode Trigger system reset on timeout when 1, trigger interrupt on timeout when 0.
* @param[in] lock Control register will be locked when 1 (unitl next reset).
* @param[in] lock Control register will be locked when 1 (until next reset).
**************************************************************************/
void neorv32_wdt_setup(uint8_t prsc, uint8_t mode, uint8_t lock) {
 
91,7 → 91,7
/**********************************************************************//**
* Disable watchdog timer.
*
* @return Returns 0 if WDT is really deativated, -1 otherwise.
* @return Returns 0 if WDT is really deactivated, -1 otherwise.
**************************************************************************/
int neorv32_wdt_disable(void) {
/lib/source/neorv32_xirq.c
0,0 → 1,219
// #################################################################################################
// # << NEORV32: neorv32_xirq.c - External Interrupt controller HW Driver >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_xirq.h
* @author Stephan Nolting
* @brief External Interrupt controller HW driver source file.
**************************************************************************/
 
#include "neorv32.h"
#include "neorv32_xirq.h"
 
 
/**********************************************************************//**
* The >private< trap vector look-up table of the XIRQ.
**************************************************************************/
static uint32_t __neorv32_xirq_vector_lut[32] __attribute__((unused)); // trap handler vector table
 
// private functions
static void __attribute__((aligned(16))) __attribute__((unused)) __neorv32_xirq_core(void);
static void __attribute__((unused)) __neorv32_xirq_dummy_handler(void);
 
 
/**********************************************************************//**
* Check if external interrupt controller was synthesized.
*
* @return 0 if XIRQ was not synthesized, 1 if EXTIRQ is available.
**************************************************************************/
int neorv32_xirq_available(void) {
 
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_XIRQ)) {
return 1;
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Initialize XIRQ controller.
*
* @note All interrupt channels will be deactivated, all pending IRQs will be deleted and all
* handler addresses will be deleted.
* @return 0 if success, 1 if error.
**************************************************************************/
int neorv32_xirq_setup(void) {
 
XIRQ_IER = 0; // disable all input channels
XIRQ_IPR = 0xffffffff; // clear/ack all pending IRQs
 
int i;
for (i=0; i<32; i++) {
__neorv32_xirq_vector_lut[i] = (uint32_t)(&__neorv32_xirq_dummy_handler);
}
 
// register XIRQ handler in RTE
return neorv32_rte_exception_install(XIRQ_RTE_ID, __neorv32_xirq_core);
}
 
 
/**********************************************************************//**
* Globally enable XIRQ interrupts (via according FIRQ channel).
**************************************************************************/
void neorv32_xirq_global_enable(void) {
 
// enable XIRQ fast interrupt channel
neorv32_cpu_irq_enable(XIRQ_FIRQ_ENABLE);
}
 
 
/**********************************************************************//**
* Globally disable XIRQ interrupts (via according FIRQ channel).
**************************************************************************/
void neorv32_xirq_global_disable(void) {
 
// enable XIRQ fast interrupt channel
neorv32_cpu_irq_disable(XIRQ_FIRQ_ENABLE);
}
 
 
/**********************************************************************//**
* Get number of implemented XIRQ channels
*
* @return Number of implemented channels (0..32).
**************************************************************************/
int neorv32_xirq_get_num(void) {
 
uint32_t enable;
int i, cnt;
 
if (neorv32_xirq_available()) {
 
neorv32_cpu_irq_disable(XIRQ_FIRQ_ENABLE); // make sure XIRQ cannot fire
XIRQ_IER = 0xffffffff; // try to set all enable flags
enable = XIRQ_IER; // read back actually set flags
 
// count set bits in enable
cnt = 0;
for (i=0; i<32; i++) {
if (enable & 1) {
cnt++;
}
enable >>= 1;
}
return cnt;
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Install exception handler function for XIRQ channel.
*
* @note This will also activate the according XIRQ channel and clear a pending IRQ at this channel.
*
* @param[in] ch XIRQ interrupt channel (0..31).
* @param[in] handler The actual handler function for the specified exception (function MUST be of type "void function(void);").
* @return 0 if success, 1 if error.
**************************************************************************/
int neorv32_xirq_install(uint8_t ch, void (*handler)(void)) {
 
// channel valid?
if (ch < 32) {
__neorv32_xirq_vector_lut[ch] = (uint32_t)handler; // install handler
uint32_t mask = 1 << ch;
XIRQ_IPR = mask; // clear if pending
XIRQ_IER |= mask; // enable channel
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* Uninstall exception handler function for XIRQ channel.
*
* @note This will also deactivate the according XIRQ channel and clear pending state.
*
* @param[in] ch XIRQ interrupt channel (0..31).
* @return 0 if success, 1 if error.
**************************************************************************/
int neorv32_xirq_uninstall(uint8_t ch) {
 
// channel valid?
if (ch < 32) {
__neorv32_xirq_vector_lut[ch] = (uint32_t)(&__neorv32_xirq_dummy_handler); // override using dummy handler
uint32_t mask = 1 << ch;
XIRQ_IER &= ~mask; // disable channel
XIRQ_IPR = mask; // clear if pending
return 0;
}
return 1;
}
 
 
/**********************************************************************//**
* This is the actual second-level IRQ handler for the XIRQ. It will call the previously installed handler
* if an XIRQ fires.
*
* @note This function must no be used by the user.
**************************************************************************/
static void __attribute__((aligned(16))) __attribute__((unused)) __neorv32_xirq_core(void) {
 
register uint32_t src = XIRQ_SCR; // get IRQ source (with highest priority)
src &= 0x1f;
 
XIRQ_IPR = (uint32_t)(1 << src); // acknowledge pending interrupt
 
// execute handler
register uint32_t xirq_handler = __neorv32_xirq_vector_lut[src];
void (*handler_pnt)(void);
handler_pnt = (void*)xirq_handler;
(*handler_pnt)();
}
 
 
/**********************************************************************//**
* XIRQ dummy handler.
**************************************************************************/
static void __attribute__((unused)) __neorv32_xirq_dummy_handler(void) {
 
asm volatile ("nop");
}
 
/ocd-firmware/park_loop.S
99,4 → 99,5
addi s0, zero, SREG_EXECUTE_ACK
sw s0, DBMEM_SREG_BASE(zero) // ACK that execution is about to start
csrr s0, dscratch0 // restore s0 from dscratch0
fence.i // synchronize i-cache & prefetch with memory (program buffer)
jalr zero, zero, %lo(DBMEM_PBUF_BASE) // jump to beginning of program buffer

powered by: WebSVN 2.1.0

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