Line 349... |
Line 349... |
// do not allow user-level code to access cycle[h] CSRs
|
// do not allow user-level code to access cycle[h] CSRs
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
|
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
|
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
|
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
|
|
|
|
neorv32_cpu_csr_write(CSR_CYCLE, 1); // make sure CSR is != 0 for this test
|
|
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
neorv32_cpu_goto_user_mode();
|
neorv32_cpu_goto_user_mode();
|
{
|
{
|
// access to cycle CSR is no longer allowed
|
// access to cycle CSR is no longer allowed
|
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE);
|
asm volatile (" mv %[result], zero \n" // initialize with zero
|
|
" rdcycle %[result] " // read CSR_CYCLE, is not allowed and should not alter [result]
|
|
: [result] "=r" (tmp_a) : );
|
|
}
|
|
|
|
if (tmp_a != 0) {
|
|
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
|
}
|
}
|
|
|
// make sure there was an illegal instruction trap
|
// make sure there was an illegal instruction trap
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) && (tmp_a == 0)) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
Line 748... |
Line 756... |
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Machine timer interrupt (MTIME)
|
// Machine timer interrupt (MTIME)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MTI (via MTIME): ", cnt_test);
|
PRINT_STANDARD("[%i] MTI (MTIME): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// configure MTIME IRQ (and check overflow from low word to high word)
|
// configure MTIME IRQ (and check overflow from low word to high word)
|
neorv32_mtime_set_timecmp(-1);
|
neorv32_mtime_set_timecmp(-1);
|
Line 783... |
Line 791... |
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Machine software interrupt (MSI) via testbench
|
// Machine software interrupt (MSI) via testbench
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MSI (via testbench): ", cnt_test);
|
PRINT_STANDARD("[%i] MSI (testbench): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable interrupt
|
// enable interrupt
|
neorv32_cpu_irq_enable(CSR_MIE_MSIE);
|
neorv32_cpu_irq_enable(CSR_MIE_MSIE);
|
Line 812... |
Line 820... |
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Machine external interrupt (MEI) via testbench
|
// Machine external interrupt (MEI) via testbench
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] MEI (via testbench): ", cnt_test);
|
PRINT_STANDARD("[%i] MEI (testbench): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable interrupt
|
// enable interrupt
|
neorv32_cpu_irq_enable(CSR_MIE_MEIE);
|
neorv32_cpu_irq_enable(CSR_MIE_MEIE);
|
Line 871... |
Line 879... |
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test pending interrupt
|
// Test pending interrupt
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] Pending IRQ test (MTIME): ", cnt_test);
|
PRINT_STANDARD("[%i] Pending IRQ (MTIME): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable interrupt
|
// enable interrupt
|
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
|
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
|
Line 920... |
Line 928... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 0 (WDT)
|
// Fast interrupt channel 0 (WDT)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_wdt_available()) {
|
if (neorv32_wdt_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ0 test (via WDT): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ0 (WDT): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable fast interrupt
|
// enable fast interrupt
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E);
|
Line 934... |
Line 942... |
NEORV32_WDT.CTRL = 0; // try to deactivate WDT (should fail as access is loced)
|
NEORV32_WDT.CTRL = 0; // try to deactivate WDT (should fail as access is loced)
|
neorv32_wdt_force(); // force watchdog into action
|
neorv32_wdt_force(); // force watchdog into action
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_0) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_0) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
// disable fast interrupt
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
|
|
|
|
// no more WDT interrupts
|
// no more WDT interrupts
|
neorv32_wdt_disable();
|
neorv32_wdt_disable();
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 1 (CFS)
|
// Fast interrupt channel 1 (CFS)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
PRINT_STANDARD("[%i] FIRQ1 test (via CFS): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ1 (CFS): ", cnt_test);
|
PRINT_STANDARD("skipped \n");
|
PRINT_STANDARD("skipped \n");
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 2 (UART0.RX)
|
// Fast interrupt channel 2 (UART0.RX)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_uart1_available()) {
|
if (neorv32_uart1_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ2 test (via UART0.RX): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ2 (UART0.RX): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable fast interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E);
|
|
|
|
// wait for UART0 to finish transmitting
|
// wait for UART0 to finish transmitting
|
while(neorv32_uart0_tx_busy());
|
while(neorv32_uart0_tx_busy());
|
|
|
// backup current UART0 configuration
|
// backup current UART0 configuration
|
tmp_a = NEORV32_UART0.CTRL;
|
tmp_a = NEORV32_UART0.CTRL;
|
Line 983... |
Line 985... |
// make sure sim mode is disabled
|
// make sure sim mode is disabled
|
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
|
|
// trigger UART0 RX IRQ
|
// trigger UART0 RX IRQ
|
neorv32_uart0_putc(0);
|
neorv32_uart0_putc(0);
|
|
|
// wait for UART0 to finish transmitting
|
// wait for UART0 to finish transmitting
|
while(neorv32_uart0_tx_busy());
|
while(neorv32_uart0_tx_busy());
|
|
|
|
// enable fast interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E);
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
|
|
|
// restore original configuration
|
// restore original configuration
|
NEORV32_UART0.CTRL = tmp_a;
|
NEORV32_UART0.CTRL = tmp_a;
|
|
|
// disable fast interrupt
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
|
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 1011... |
Line 1012... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 3 (UART0.TX)
|
// Fast interrupt channel 3 (UART0.TX)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_uart0_available()) {
|
if (neorv32_uart0_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ3 test (via UART0.TX): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ3 (UART0.TX): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// UART0 TX interrupt enable
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
|
|
|
|
// wait for UART0 to finish transmitting
|
// wait for UART0 to finish transmitting
|
while(neorv32_uart0_tx_busy());
|
while(neorv32_uart0_tx_busy());
|
|
|
// backup current UART0 configuration
|
// backup current UART0 configuration
|
tmp_a = NEORV32_UART0.CTRL;
|
tmp_a = NEORV32_UART0.CTRL;
|
Line 1031... |
Line 1029... |
// make sure sim mode is disabled
|
// make sure sim mode is disabled
|
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
NEORV32_UART0.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
|
|
// trigger UART0 TX IRQ
|
// trigger UART0 TX IRQ
|
neorv32_uart0_putc(0);
|
neorv32_uart0_putc(0);
|
|
// UART0 TX interrupt enable
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
|
// wait for UART to finish transmitting
|
// wait for UART to finish transmitting
|
while(neorv32_uart0_tx_busy());
|
while(neorv32_uart0_tx_busy());
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
|
|
|
// restore original configuration
|
// restore original configuration
|
NEORV32_UART0.CTRL = tmp_a;
|
NEORV32_UART0.CTRL = tmp_a;
|
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
|
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 1058... |
Line 1055... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 4 (UART1.RX)
|
// Fast interrupt channel 4 (UART1.RX)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_uart1_available()) {
|
if (neorv32_uart1_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ4 test (via UART1.RX): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ4 (UART1.RX): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// UART1 RX interrupt enable
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
|
|
|
|
// backup current UART1 configuration
|
// backup current UART1 configuration
|
tmp_a = NEORV32_UART1.CTRL;
|
tmp_a = NEORV32_UART1.CTRL;
|
|
|
// make sure UART is enabled
|
// make sure UART is enabled
|
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
|
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
|
// make sure sim mode is disabled
|
// make sure sim mode is disabled
|
NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
|
|
// trigger UART1 RX IRQ
|
// trigger UART1 RX IRQ
|
neorv32_uart1_putc(0);
|
neorv32_uart1_putc(0);
|
|
|
// wait for UART1 to finish transmitting
|
// wait for UART1 to finish transmitting
|
while(neorv32_uart1_tx_busy());
|
while(neorv32_uart1_tx_busy());
|
|
// UART1 RX interrupt enable
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
|
|
|
// restore original configuration
|
// restore original configuration
|
NEORV32_UART1.CTRL = tmp_a;
|
NEORV32_UART1.CTRL = tmp_a;
|
|
|
// disable fast interrupt
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
|
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_4) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_4) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 1103... |
Line 1095... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 5 (UART1.TX)
|
// Fast interrupt channel 5 (UART1.TX)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_uart1_available()) {
|
if (neorv32_uart1_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ5 test (via UART1.TX): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ5 (UART1.TX): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// UART1 RX interrupt enable
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
|
|
|
|
// backup current UART1 configuration
|
// backup current UART1 configuration
|
tmp_a = NEORV32_UART1.CTRL;
|
tmp_a = NEORV32_UART1.CTRL;
|
|
|
// make sure UART is enabled
|
// make sure UART is enabled
|
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
|
NEORV32_UART1.CTRL |= (1 << UART_CTRL_EN);
|
// make sure sim mode is disabled
|
// make sure sim mode is disabled
|
NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
NEORV32_UART1.CTRL &= ~(1 << UART_CTRL_SIM_MODE);
|
|
|
// trigger UART1 TX IRQ
|
// trigger UART1 TX IRQ
|
neorv32_uart1_putc(0);
|
neorv32_uart1_putc(0);
|
|
// UART1 RX interrupt enable
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
|
// wait for UART1 to finish transmitting
|
// wait for UART1 to finish transmitting
|
while(neorv32_uart1_tx_busy());
|
while(neorv32_uart1_tx_busy());
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
|
|
|
// restore original configuration
|
// restore original configuration
|
NEORV32_UART1.CTRL = tmp_a;
|
NEORV32_UART1.CTRL = tmp_a;
|
|
|
// disable fast interrupt
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
|
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_5) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_5) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 1148... |
Line 1135... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 6 (SPI)
|
// Fast interrupt channel 6 (SPI)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_spi_available()) {
|
if (neorv32_spi_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ6 test (via SPI): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ6 (SPI): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable fast interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ6E);
|
|
|
|
// configure SPI
|
// configure SPI
|
neorv32_spi_setup(CLK_PRSC_2, 0, 0);
|
neorv32_spi_setup(CLK_PRSC_2, 0, 0, 0);
|
|
|
// trigger SPI IRQ
|
// trigger SPI IRQ
|
neorv32_spi_trans(0);
|
neorv32_spi_trans(0);
|
|
// enable fast interrupt
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ6E);
|
while(neorv32_spi_busy()); // wait for current transfer to finish
|
while(neorv32_spi_busy()); // wait for current transfer to finish
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ6E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_6) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_6) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
// disable SPI
|
// disable SPI
|
neorv32_spi_disable();
|
neorv32_spi_disable();
|
|
|
// disable fast interrupt
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ6E);
|
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 7 (TWI)
|
// Fast interrupt channel 7 (TWI)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_twi_available()) {
|
if (neorv32_twi_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ7 test (via TWI): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ7 (TWI): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// configure TWI, fastest clock, no peripheral clock stretching
|
// configure TWI, fastest clock, no peripheral clock stretching
|
neorv32_twi_setup(CLK_PRSC_2, 0);
|
neorv32_twi_setup(CLK_PRSC_2, 0);
|
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ7E);
|
|
|
|
// trigger TWI IRQ
|
// trigger TWI IRQ
|
neorv32_twi_generate_start();
|
neorv32_twi_generate_start();
|
neorv32_twi_trans(0);
|
neorv32_twi_trans(0);
|
neorv32_twi_generate_stop();
|
neorv32_twi_generate_stop();
|
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ7E);
|
|
|
// wait some time for the IRQ to arrive the CPU
|
// wait some time for the IRQ to arrive the CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ7E);
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_7) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_7) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
// disable TWI
|
// disable TWI
|
neorv32_twi_disable();
|
neorv32_twi_disable();
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ7E);
|
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Fast interrupt channel 8 (XIRQ)
|
// Fast interrupt channel 8 (XIRQ)
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ8 test (via XIRQ): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ8 (XIRQ): ", cnt_test);
|
if (neorv32_xirq_available()) {
|
if (neorv32_xirq_available()) {
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
int xirq_err_cnt = 0;
|
int xirq_err_cnt = 0;
|
Line 1242... |
Line 1223... |
neorv32_gpio_port_set(3);
|
neorv32_gpio_port_set(3);
|
|
|
// wait for IRQs to arrive CPU
|
// wait for IRQs to arrive CPU
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
|
|
|
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_8) && // FIRQ8 IRQ
|
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_8) && // FIRQ8 IRQ
|
(xirq_err_cnt == 0) && // no errors during XIRQ configuration
|
(xirq_err_cnt == 0) && // no errors during XIRQ configuration
|
(xirq_trap_handler_ack == 4)) { // XIRQ channel handler 0 executed before handler 1
|
(xirq_trap_handler_ack == 4)) { // XIRQ channel handler 0 executed before handler 1
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
|
|
NEORV32_XIRQ.IER = 0;
|
NEORV32_XIRQ.IER = 0;
|
NEORV32_XIRQ.IPR = -1;
|
NEORV32_XIRQ.IPR = -1;
|
}
|
}
|
|
|
|
|
Line 1272... |
Line 1252... |
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
if (neorv32_slink_available()) {
|
if (neorv32_slink_available()) {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test);
|
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test);
|
|
|
// NOTE: this test requires FIFO sizes = 1
|
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// enable SLINK
|
// enable SLINK
|
neorv32_slink_enable();
|
neorv32_slink_enable();
|
|
|
|
// configure SLINK IRQs
|
|
neorv32_slink_tx_irq_config(0, SLINK_IRQ_ENABLE, SLINK_IRQ_TX_NOT_FULL);
|
|
neorv32_slink_rx_irq_config(0, SLINK_IRQ_ENABLE, SLINK_IRQ_RX_NOT_EMPTY);
|
|
|
// enable SLINK FIRQs
|
// enable SLINK FIRQs
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ10E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ10E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ11E);
|
neorv32_cpu_irq_enable(CSR_MIE_FIRQ11E);
|
|
|
tmp_a = 0; // error counter
|
tmp_a = 0; // error counter
|
|
|
|
// wait some time for the IRQ to arrive the CPU
|
|
asm volatile("nop");
|
|
|
|
// check if TX FIFO fires IRQ
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_FIRQ_11) {
|
|
tmp_a += 1;
|
|
}
|
|
neorv32_slink_tx_irq_config(0, SLINK_IRQ_DISABLE, SLINK_IRQ_TX_NOT_FULL);
|
|
|
// send single data word via link 0
|
// send single data word via link 0
|
if (neorv32_slink_tx0_nonblocking(0xA1B2C3D4)) {
|
if (neorv32_slink_tx0_nonblocking(0xA1B2C3D4)) {
|
tmp_a++; // sending failed
|
tmp_a += 2; // sending failed
|
|
}
|
|
|
|
// wait some time for the IRQ to arrive the CPU
|
|
asm volatile("nop");
|
|
|
|
// check if RX FIFO fires IRQ
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_FIRQ_10) {
|
|
tmp_a += 4;
|
}
|
}
|
|
neorv32_slink_rx_irq_config(0, SLINK_IRQ_DISABLE, SLINK_IRQ_RX_NOT_EMPTY);
|
|
|
// get single data word from link 0
|
// get single data word from link 0
|
uint32_t slink_rx_data;
|
uint32_t slink_rx_data;
|
if (neorv32_slink_rx0_nonblocking(&slink_rx_data)) {
|
if (neorv32_slink_rx0_nonblocking(&slink_rx_data)) {
|
tmp_a++; // receiving failed
|
tmp_a += 8; // receiving failed
|
}
|
}
|
|
|
// wait some time for the IRQ to arrive the CPU
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ10E);
|
asm volatile("nop");
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ11E);
|
asm volatile("nop");
|
|
|
|
tmp_b = neorv32_cpu_csr_read(CSR_MCAUSE);
|
if ((tmp_a == 0) && // local error counter = 0
|
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
|
(slink_rx_data == 0xA1B2C3D4)) { // correct data read-back
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
// shutdown SLINK
|
// shutdown SLINK
|
neorv32_slink_disable();
|
neorv32_slink_disable();
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ10E);
|
|
neorv32_cpu_irq_disable(CSR_MIE_FIRQ11E);
|
|
}
|
}
|
|
|
|
|
//// ----------------------------------------------------------
|
//// ----------------------------------------------------------
|
//// Fast interrupt channel 12..15 (reserved)
|
//// Fast interrupt channel 12..15 (reserved)
|
Line 1328... |
Line 1323... |
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test WFI ("sleep") instructions, wakeup via MTIME
|
// Test WFI ("sleep") instructions, wakeup via MTIME
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] WFI (sleep instruction) test (wake-up via MTIME): ", cnt_test);
|
PRINT_STANDARD("[%i] WFI (sleep instruction, wake-up via MTIME): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// clear timeout wait flag
|
|
tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS);
|
|
tmp_a &= ~(1 << CSR_MSTATUS_TW);
|
|
neorv32_cpu_csr_write(CSR_MSTATUS, tmp_a);
|
|
|
|
// program wake-up timer
|
// program wake-up timer
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500);
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500);
|
|
|
// enable interrupt
|
// enable mtime interrupt
|
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
|
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
|
|
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
// put CPU into sleep mode
|
neorv32_cpu_goto_user_mode();
|
asm volatile ("wfi");
|
{
|
|
// only when mstatus.TW = 0 executing WFI in user mode is allowed
|
|
asm volatile ("wfi"); // put CPU into sleep mode
|
|
}
|
|
|
|
// no more mtime interrupts
|
// no more mtime interrupts
|
neorv32_cpu_irq_disable(CSR_MIE_MTIE);
|
neorv32_cpu_irq_disable(CSR_MIE_MTIE);
|
neorv32_mtime_set_timecmp(-1);
|
neorv32_mtime_set_timecmp(-1);
|
|
|
Line 1438... |
Line 1424... |
|
|
if ((pmp_return == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
|
if ((pmp_return == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
|
if (neorv32_cpu_csr_read(CSR_PMPCFG0) & 0x80) {
|
|
PRINT_CRITICAL("%c[1m<Entry LOCKED!> %c[0m\n", 27, 27);
|
|
}
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
|
|
// ------ EXECUTE: should fail ------
|
// ------ EXECUTE: should fail ------
|
Line 1602... |
Line 1591... |
|
|
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xAABBCCDD);
|
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xAABBCCDD);
|
|
|
// atomic access
|
// atomic access
|
tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation
|
tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation
|
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xDEADDEAD); // destroy reservation
|
// neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xDEADDEAD); // destroy reservation
|
|
neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr); // destroy reservation
|
tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688);
|
tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688);
|
|
|
if ((tmp_b != 0) && // status: fail
|
if ((tmp_b != 0) && // status: fail
|
(tmp_a == 0xAABBCCDD) && // correct data read
|
(tmp_a == 0xAABBCCDD) && // correct data read
|
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0xDEADDEAD)) { // correct data write
|
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0xAABBCCDD)) { // correct data write
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|