stnolting / neorv32

:desktop_computer: A small, customizable and extensible MCU-class 32-bit RISC-V soft-core CPU and microcontroller-like SoC written in platform-independent VHDL.
https://neorv32.org
BSD 3-Clause "New" or "Revised" License
1.55k stars 214 forks source link

XIRQ is firing continuously #443

Closed AWenzel83 closed 1 year ago

AWenzel83 commented 1 year ago

Hello,

I am trying to use external Interrupts.

In my ProcessorTop-Template (neorv32_SystemTop_axi4lite) I changed the number of XIRQ-Channels to 4, I left trigger-type and polarity at 0xFFFFFFFF, which should result in interrupts on a rising edge. I connected the 4 input channels to 4 high-active buttons.

In the firmware I used

neorv32_rte_setup();
neorv32_xirq_setup();
neorv32_xirq_install(0, xirq_handler);
neorv32_xirq_global_enable();

and

neorv32_cpu_eint(); 

to setup and enable interrupts

Whenever I push a button, the corresponding handler gets executed continuously. I tried to clear the pending interrupt inside the handler, but that doesn't change anything.

I also tried the XIRQ-Demo on my and a another minimal design (neorv32_ProcessorTop_MinimalBoot), where I connected gpio_o(31 downto 0) to xirq_i with the same result, the interrupt handler is firing continuously:

...
XIRQ interrupt from channel 3<\r><\n>
XIRQ interrupt from channel 3<\r><\n>
XIRQ interrupt from channel 3<\r><\n>
XIRQ interrupt from channel 3<\r><\n>
XIRQ interrupt from channel 3<\r><\n>
...

I have an older design (v1.6.4.2) here, and there it works as expected...

akaeba commented 1 year ago

Hi,

Whenever I push a button

Just to ensure, you debounce the button?

Do you have a running simulation from your core configuration? Especially the _cpu_irqo from https://github.com/stnolting/neorv32/blob/278ab39682ead6c76164f426e4838bd33be11cc8/rtl/core/neorv32_xirq.vhd would be interesting.

andkae commented 1 year ago

Hi Stephan, i checked on my design. Same for me the NEORV32 craches with an RTE:

# <RTE> Illegal instruction @ PC=0x80000000, INST=0x0042 </RTE>
# <RTE> Illegal instruction @ PC=0x80000004, INST=0x0000 </RTE>

@AWenzel83: If you like to double check, add neorv32_rte_setup(); to your c program and dump from the UART.

BR, Andeas

andkae commented 1 year ago

One additional hint from my site, i use riscv32-unknown-elf.gcc-10.2.0.rv32i.ilp32.newlib.tar.gz as compiler.

stnolting commented 1 year ago

@AWenzel83

Hey there!

trigger-type and polarity at 0xFFFFFFFF, which should result in interrupts on a rising edge. I connected the 4 input channels to 4 high-active buttons.

I have the same setup here but I cannot reproduce your issue. The external interrupts fire as expected. Are you using the latest version of the core? Could you share the code for your xirq_handler function?


@akaeba

i checked on my design. Same for me the NEORV32 craches with an RTE:

Oh, that looks bad... But I think this might be caused by a compiler issue. How did you compile your executable? Could you also share the code that causes this exception?

i use riscv32-unknown-elf.gcc-10.2.0.rv32i.ilp32.newlib.tar.gz as compiler

This version is outdated, but it should still work... However, could you try updating to a newer version? For example this one: https://github.com/stnolting/riscv-gcc-prebuilt/releases/tag/rv32i-4.0.0

andkae commented 1 year ago

Hi Stephan,

This version is outdated, but it should still work... However, could you try updating to a newer version? For example this one: https://github.com/stnolting/riscv-gcc-prebuilt/releases/tag/rv32i-4.0.0

With version v4.0.0 is all fine :) Final question for me: has my MIF convertor a bug, or depends it on the GCC. But now for me issue solved. Thanks for supporting :)

stnolting commented 1 year ago

With version v4.0.0 is all fine :)

Great to hear!

Final question for me: has my MIF convertor a bug, or depends it on the GCC

I'm not sure... But this

# <RTE> Illegal instruction @ PC=0x80000000, INST=0x0042 </RTE>

looks like a broken executable. The data memory starts at address 0x80000000 and the CPU should not try executing code from there as this is where the .data segment is located. 🤔

AWenzel83 commented 1 year ago

Sorry for the late reply, I haven't been in the office in the last week.

If you like to double check, add neorv32_rte_setup(); to your c program and dump from the UART.

I had that in the original version, posted above. Its not dumping anything to the UART.

Just to ensure, you debounce the button?

Yes, I do. But the problem also exists in the XIRQ-Example, where the interrupts are triggered in software.

Are you using the latest version of the core?

not quite, I'm on Version 1.7.7.1. Since I didn't want to change my code for the updated TWI- and SPI-Interfaces, but I will try the newest version, next.

Could you share the code for your xirq_handler function?

sure, its pretty simple:

void xirq_handler(void)
{
  neorv32_uart0_printf("Interrupt\n");
  NEORV32_GPIO.OUTPUT_LO ^= 0x400;
}

Do you have a running simulation from your core configuration? Especially the cpu_irq_o from https://github.com/stnolting/neorv32/blob/278ab39682ead6c76164f426e4838bd33be11cc8/rtl/core/neorv32_xirq.vhd would be interesting.

I haven't, but I will look into that.

With version v4.0.0 is all fine :)

I tried that one, too. I used my own toolchain built with crosstool-ng, before. Unfortunately that didn't resolve my problem.

stnolting commented 1 year ago

Sorry for the late reply, I haven't been in the office in the last week.

No problem!

I'm on Version 1.7.7.1. Since I didn't want to change my code for the updated TWI- and SPI-Interfaces, but I will try the newest version, next.

The modifications of the SPI and TWI modules should be "quite" backwards-compatible (with some minor exceptions)... 😅


I have setup a minimal program to check the XIRQ again:

#include <neorv32.h>

#define BAUD_RATE 19200

void xirq_handler(void)
{
  neorv32_uart0_printf("Interrupt\n");
  NEORV32_GPIO.OUTPUT_LO ^= 0x400;
}

int main() {

  neorv32_rte_setup();

  neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);

  neorv32_gpio_port_set(0);

  neorv32_xirq_setup();
  neorv32_xirq_install(0, xirq_handler);
  neorv32_xirq_install(1, xirq_handler);
  neorv32_xirq_install(2, xirq_handler);
  neorv32_xirq_install(3, xirq_handler);
  neorv32_xirq_global_enable();

  neorv32_cpu_eint();

  while(1);

  return 0;
}

Compiled with make MARCH=rv32i clean_all exe and executed on my default setup using the following XIRQ configs:

    -- External Interrupts Controller (XIRQ) --
    XIRQ_NUM_CH                  => 4,
    XIRQ_TRIGGER_TYPE            => (others => '1'),
    XIRQ_TRIGGER_POLARITY        => (others => '1'),

I have connected 4 high-active push buttons (no debouncing) and everything works as expected. The interrupts fire once (or twice, when pushed "too slow" due to bouncing...) when I hit any of the buttons:

Awaiting neorv32_exe.bin... OK
CMD:> e
Booting from 0x00000000...

Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt

Maybe it is a stupid question, but did you use pull-down resistors for each XIRQ input?

AWenzel83 commented 1 year ago

I tried again, this time with the current release Version 1.7.8 and what should I say, the exact same design works like expected...

I don't really know what changed between these Versions, I guess I broke something on my side...

Thank you for the help