enjoy-digital / litex

Build your hardware, easily!
Other
3.04k stars 573 forks source link

Zephyr support on LiteX/NaxRiscv #1754

Closed ytsuchiya-upwind closed 1 year ago

ytsuchiya-upwind commented 1 year ago

Hello. Thanks to @Dolu1990's advice on SpinalHDL/VexRiscv Gitter, I got Zephyr on Litex/NaxRiscv bootable with PLIC interrupt controller.

However, I have the following two issues:

Using polling mode for UART on Zephyr (CONFIG_UART_INTERRUPT_DRIVEN is not defined) , so it should not be related to interrupt I guess but... I'm not completely sure.

Also, I'm not yet sure in which layer (Zephyr?, LiteX/NaxRiscv?) the issue exists.

Regarding the LiteX/NaxRiscv layer, I found functions under soc/cores/cpu/naxriscv/irq.h are not implemented (same as vexriscv-smp)

Do you think I need to implement it? That being said...

I want to make sure for the next step.

Thank you.


Zephyr changes

Here are the changes made to Zephyr for the record:

diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi
index 9ca18b0532..90e50cd2cc 100644
--- a/dts/riscv/riscv32-litex-vexriscv.dtsi
+++ b/dts/riscv/riscv32-litex-vexriscv.dtsi
@@ -30,6 +30,12 @@
            riscv,isa = "rv32imac";
            status = "okay";
            timebase-frequency = <32768>;
+
+           L0: interrupt-controller {
+               #interrupt-cells = <0x00000001>;
+               interrupt-controller;
+               compatible = "riscv,cpu-intc";
+           };
        };
    };
    soc {
@@ -37,14 +43,18 @@
        #size-cells = <1>;
        compatible = "litex,vexriscv";
        ranges;
-       intc0: interrupt-controller@bc0 {
-           compatible = "vexriscv-intc0";
+       intc0: interrupt-controller@f0c00000 {
+           compatible = "sifive,plic-1.0.0";
            #address-cells = <0>;
            #interrupt-cells = <2>;
            interrupt-controller;
-           reg = <0xbc0 0x4 0xfc0 0x4>;
-           reg-names = "irq_mask", "irq_pending";
+           reg = <0xf0c00000 0x00002000
+                  0xf0c02000 0x001fe000
+                  0xf0e00000 0x03e00000>;
+           reg-names = "prio", "irq_en", "reg";
+           interrupts-extended = <&L0 11 &L0 9>;
            riscv,max-priority = <7>;
+           riscv,ndev = <52>;
        };
        uart0: serial@e0001800 {
            compatible = "litex,uart0";
diff --git a/soc/riscv/litex-vexriscv/CMakeLists.txt b/soc/riscv/litex-vexriscv/CMakeLists.txt
index 34d6046ab6..827cf5fda1 100644
--- a/soc/riscv/litex-vexriscv/CMakeLists.txt
+++ b/soc/riscv/litex-vexriscv/CMakeLists.txt
@@ -7,4 +7,5 @@
 zephyr_sources(
     ../riscv-privileged/common/soc_irq.S
     ../riscv-privileged/common/vector.S
+    ../riscv-privileged/common/soc_common_irq.c
 )
diff --git a/soc/riscv/litex-vexriscv/Kconfig.defconfig b/soc/riscv/litex-vexriscv/Kconfig.defconfig
index 9447948b56..2da1a8e17e 100644
--- a/soc/riscv/litex-vexriscv/Kconfig.defconfig
+++ b/soc/riscv/litex-vexriscv/Kconfig.defconfig
@@ -9,13 +9,28 @@ config SOC
 config SYS_CLOCK_HW_CYCLES_PER_SEC
    default 100000000

+config RISCV_SOC_INTERRUPT_INIT
+   default y
+
 config RISCV_HAS_CPU_IDLE
-   bool
+   default y

 config RISCV_HAS_PLIC
-   bool
+   default y

-config NUM_IRQS
+config RISCV_GP
+   default y
+
+config 2ND_LVL_ISR_TBL_OFFSET
    default 12

+config 2ND_LVL_INTR_00_OFFSET
+   default 11
+
+config MAX_IRQ_PER_AGGREGATOR
+   default 52
+
+config NUM_IRQS
+   default 64
+
 endif # SOC_RISCV32_LITEX_VEXRISCV

bitstream generationn

Here is how I generate bitstream for my Arty-A7 100T board for the record. If needed, I can try to reproduce the issue using a sim environment.

python3 -m litex_boards.targets.digilent_arty \
    --variant=a7-100 \
    --cpu-type=naxriscv \
    `# --with-jtag-tap` \
    --with-jtag-instruction \
    --with-ethernet \
    --with-pmod-gpio \
    --timer-uptime \
    --with-spi-flash \
    --with-fpu \
    --output-dir ~/litex/build_naxriscv_w_jtag_inst \
    --soc-csv ~/litex/build_naxriscv_w_jtag_inst/soc.csv \
    --csr-json ~/litex/build_naxriscv_w_jtag_inst/csr.json \
    --csr-csv ~/litex/build_naxriscv_w_jtag_inst/csr.csv \
    --doc \
    --build \
    --flash

For the other steps needed to boot Zephyr, I followed the following Zephyr document

ytsuchiya-upwind commented 1 year ago

Later, I found I also need CLINT and to use riscv_machine_timer instead of litex_timer.

Closing this issue as there is no issue on the LiteX side.


Zephyr changes

Here are the changes to Zephry that UART is working, for the record. (Of course I need to prepare dedicated litex-naxriscv board files later instead of rewriting litex-vexriscv files.)

diff --git a/boards/riscv/litex_vexriscv/litex_vexriscv.dts b/boards/riscv/litex_vexriscv/litex_vexriscv.dts
index eab0c15266..7e1671f943 100644
--- a/boards/riscv/litex_vexriscv/litex_vexriscv.dts
+++ b/boards/riscv/litex_vexriscv/litex_vexriscv.dts
@@ -28,10 +28,6 @@
    current-speed = <115200>;
 };

-&timer0 {
-   status = "okay";
-};
-
 &eth0 {
    status = "okay";
 };
@@ -26,6 +30,12 @@
            riscv,isa = "rv32imac";
            status = "okay";
            timebase-frequency = <32768>;
+
+           L0: interrupt-controller {
+               #interrupt-cells = <0x00000001>;
+               interrupt-controller;
+               compatible = "riscv,cpu-intc";
+           };
        };
    };
    soc {
@@ -33,14 +43,23 @@
        #size-cells = <1>;
        compatible = "litex,vexriscv";
        ranges;
-       intc0: interrupt-controller@bc0 {
-           compatible = "vexriscv-intc0";
+       clint: clint@f0010000 {
+           compatible = "sifive,clint0";
+           interrupts-extended = <&L0 3 &L0 7>;
+           reg = <0xf0010000 0x10000>;
+       };
+       intc0: interrupt-controller@f0c00000 {
+           compatible = "sifive,plic-1.0.0";
            #address-cells = <0>;
            #interrupt-cells = <2>;
            interrupt-controller;
-           reg = <0xbc0 0x4 0xfc0 0x4>;
-           reg-names = "irq_mask", "irq_pending";
+           reg = <0xf0c00000 0x00002000
+                  0xf0c02000 0x001fe000
+                  0xf0e00000 0x03e00000>;
+           reg-names = "prio", "irq_en", "reg";
+           interrupts-extended = <&L0 11 &L0 9>;
            riscv,max-priority = <7>;
+           riscv,ndev = <32>;
        };
        uart0: serial@e0001800 {
            compatible = "litex,uart0";
diff --git a/soc/riscv/litex-vexriscv/CMakeLists.txt b/soc/riscv/litex-vexriscv/CMakeLists.txt
index 34d6046ab6..1ce80199f8 100644
--- a/soc/riscv/litex-vexriscv/CMakeLists.txt
+++ b/soc/riscv/litex-vexriscv/CMakeLists.txt
@@ -7,4 +7,6 @@
 zephyr_sources(
     ../riscv-privileged/common/soc_irq.S
     ../riscv-privileged/common/vector.S
+    ../riscv-privileged/common/soc_common_irq.c
+    ../riscv-privileged/common/idle.c
 )
diff --git a/soc/riscv/litex-vexriscv/Kconfig.defconfig b/soc/riscv/litex-vexriscv/Kconfig.defconfig
index 9447948b56..93f6aad955 100644
--- a/soc/riscv/litex-vexriscv/Kconfig.defconfig
+++ b/soc/riscv/litex-vexriscv/Kconfig.defconfig
@@ -9,13 +9,28 @@ config SOC
 config SYS_CLOCK_HW_CYCLES_PER_SEC
    default 100000000

+config RISCV_SOC_INTERRUPT_INIT
+   default y
+
 config RISCV_HAS_CPU_IDLE
-   bool
+   default y

 config RISCV_HAS_PLIC
-   bool
+   default y

-config NUM_IRQS
+config RISCV_GP
+   default y
+
+config 2ND_LVL_ISR_TBL_OFFSET
    default 12

+config 2ND_LVL_INTR_00_OFFSET
+   default 11
+
+config MAX_IRQ_PER_AGGREGATOR
+   default 32
+
+config NUM_IRQS
+   default 64
+
 endif # SOC_RISCV32_LITEX_VEXRISCV
Dolu1990 commented 1 year ago

Thanks for the feedback :)