From 63ab2f4308a0aa3dc6cb3bcf89ec7899b3c5ae65 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Sun, 5 Dec 2021 21:41:44 +0800 Subject: [PATCH] arch/risc-v: Introduce basic support for qemu rv32 Signed-off-by: Huang Qi --- arch/risc-v/Kconfig | 10 + arch/risc-v/include/qemu-rv32/chip.h | 24 ++ arch/risc-v/include/qemu-rv32/irq.h | 63 +++++ arch/risc-v/src/qemu-rv32/Kconfig | 0 arch/risc-v/src/qemu-rv32/Make.defs | 47 ++++ arch/risc-v/src/qemu-rv32/chip.h | 45 ++++ .../src/qemu-rv32/hardware/qemu_rv32_clint.h | 31 +++ .../qemu-rv32/hardware/qemu_rv32_memorymap.h | 33 +++ .../src/qemu-rv32/hardware/qemu_rv32_plic.h | 35 +++ arch/risc-v/src/qemu-rv32/qemu_rv32_head.S | 227 ++++++++++++++++++ arch/risc-v/src/qemu-rv32/qemu_rv32_idle.c | 69 ++++++ arch/risc-v/src/qemu-rv32/qemu_rv32_irq.c | 209 ++++++++++++++++ .../src/qemu-rv32/qemu_rv32_irq_dispatch.c | 112 +++++++++ .../src/qemu-rv32/qemu_rv32_memorymap.h | 43 ++++ arch/risc-v/src/qemu-rv32/qemu_rv32_start.c | 101 ++++++++ .../risc-v/src/qemu-rv32/qemu_rv32_timerisr.c | 127 ++++++++++ arch/risc-v/src/qemu-rv32/qemu_rv32_vectors.S | 34 +++ boards/Kconfig | 11 + boards/risc-v/qemu-rv32/rv32-virt/Kconfig | 0 boards/risc-v/qemu-rv32/rv32-virt/README.txt | 31 +++ .../qemu-rv32/rv32-virt/configs/nsh/defconfig | 66 +++++ .../qemu-rv32/rv32-virt/include/board.h | 78 ++++++ .../rv32-virt/include/nsh_romfsimg.h | 25 ++ .../qemu-rv32/rv32-virt/scripts/Make.defs | 64 +++++ .../qemu-rv32/rv32-virt/scripts/ld.script | 119 +++++++++ .../risc-v/qemu-rv32/rv32-virt/src/.gitignore | 2 + .../risc-v/qemu-rv32/rv32-virt/src/Makefile | 27 +++ .../qemu-rv32/rv32-virt/src/etc/init.d/rcS | 0 .../rv32-virt/src/qemu_rv32_appinit.c | 80 ++++++ 29 files changed, 1713 insertions(+) create mode 100644 arch/risc-v/include/qemu-rv32/chip.h create mode 100644 arch/risc-v/include/qemu-rv32/irq.h create mode 100644 arch/risc-v/src/qemu-rv32/Kconfig create mode 100644 arch/risc-v/src/qemu-rv32/Make.defs create mode 100644 arch/risc-v/src/qemu-rv32/chip.h create mode 100644 arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_clint.h create mode 100644 arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_memorymap.h create mode 100644 arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_plic.h create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_head.S create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_idle.c create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_irq.c create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_irq_dispatch.c create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_memorymap.h create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_start.c create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_timerisr.c create mode 100644 arch/risc-v/src/qemu-rv32/qemu_rv32_vectors.S create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/Kconfig create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/README.txt create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/configs/nsh/defconfig create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/include/board.h create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/include/nsh_romfsimg.h create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/scripts/Make.defs create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/src/.gitignore create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/src/Makefile create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/src/etc/init.d/rcS create mode 100644 boards/risc-v/qemu-rv32/rv32-virt/src/qemu_rv32_appinit.c diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 3543d3aba8..01925050ab 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -86,6 +86,12 @@ config ARCH_CHIP_RV32M1 ---help--- NXP RV32M1 processor (RISC-V Core with PULP extensions). +config ARCH_CHIP_QEMU_RV32 + bool "QEMU RV32" + select ARCH_RV32IM + ---help--- + QEMU Generic RV32 processor + config ARCH_CHIP_RISCV_CUSTOM bool "Custom RISC-V chip" select ARCH_CHIP_CUSTOM @@ -125,6 +131,7 @@ config ARCH_CHIP default "c906" if ARCH_CHIP_C906 default "mpfs" if ARCH_CHIP_MPFS default "rv32m1" if ARCH_CHIP_RV32M1 + default "qemu-rv32" if ARCH_CHIP_QEMU_RV32 config ARCH_RISCV_INTXCPT_EXTENSIONS bool "RISC-V Integer Context Extensions" @@ -171,4 +178,7 @@ endif if ARCH_CHIP_RV32M1 source "arch/risc-v/src/rv32m1/Kconfig" endif +if ARCH_CHIP_QEMU_RV32 +source "arch/risc-v/src/qemu-rv32/Kconfig" +endif endif diff --git a/arch/risc-v/include/qemu-rv32/chip.h b/arch/risc-v/include/qemu-rv32/chip.h new file mode 100644 index 0000000000..dffbf7bb9d --- /dev/null +++ b/arch/risc-v/include/qemu-rv32/chip.h @@ -0,0 +1,24 @@ +/**************************************************************************** + * arch/risc-v/include/qemu-rv32/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_QEMU_RV32_CHIP_H +#define __ARCH_RISCV_INCLUDE_QEMU_RV32_CHIP_H + +#endif /* __ARCH_RISCV_INCLUDE_QEMU_RV32_CHIP_H */ diff --git a/arch/risc-v/include/qemu-rv32/irq.h b/arch/risc-v/include/qemu-rv32/irq.h new file mode 100644 index 0000000000..dba40d7340 --- /dev/null +++ b/arch/risc-v/include/qemu-rv32/irq.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/risc-v/include/qemu-rv32/irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_QEMU_RV32_IRQ_H +#define __ARCH_RISCV_INCLUDE_QEMU_RV32_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Map RISC-V exception code to NuttX IRQ */ + +/* IRQ 0-15 : (exception:interrupt=0) */ + +#define QEMU_RV32_IRQ_IAMISALIGNED (0) /* Instruction Address Misaligned */ +#define QEMU_RV32_IRQ_IAFAULT (1) /* Instruction Address Fault */ +#define QEMU_RV32_IRQ_IINSTRUCTION (2) /* Illegal Instruction */ +#define QEMU_RV32_IRQ_BPOINT (3) /* Break Point */ +#define QEMU_RV32_IRQ_LAMISALIGNED (4) /* Load Address Misaligned */ +#define QEMU_RV32_IRQ_LAFAULT (5) /* Load Access Fault */ +#define QEMU_RV32_IRQ_SAMISALIGNED (6) /* Store/AMO Address Misaligned */ +#define QEMU_RV32_IRQ_SAFAULT (7) /* Store/AMO Access Fault */ +#define QEMU_RV32_IRQ_ECALLU (8) /* Environment Call from U-mode */ + /* 9-10: Reserved */ + +#define QEMU_RV32_IRQ_ECALLM (11) /* Environment Call from M-mode */ + /* 12-15: Reserved */ + +/* IRQ 16- : (async event:interrupt=1) */ + +#define QEMU_RV32_IRQ_ASYNC (16) +#define QEMU_RV32_IRQ_MSOFT (QEMU_RV32_IRQ_ASYNC + 3) /* Machine Software Int */ +#define QEMU_RV32_IRQ_MTIMER (QEMU_RV32_IRQ_ASYNC + 7) /* Machine Timer Int */ +#define QEMU_RV32_IRQ_MEXT (QEMU_RV32_IRQ_ASYNC + 11) /* Machine External Int */ + +#define QEMU_RV32_IRQ_UART0 (QEMU_RV32_IRQ_MEXT + 10) + +#define NR_IRQS (QEMU_RV32_IRQ_UART0 + 1) + +#endif /* __ARCH_RISCV_INCLUDE_QEMU_RV32_IRQ_H */ diff --git a/arch/risc-v/src/qemu-rv32/Kconfig b/arch/risc-v/src/qemu-rv32/Kconfig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/arch/risc-v/src/qemu-rv32/Make.defs b/arch/risc-v/src/qemu-rv32/Make.defs new file mode 100644 index 0000000000..cb579f96e0 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/Make.defs @@ -0,0 +1,47 @@ +############################################################################ +# arch/risc-v/src/qemu-rv32/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Specify our HEAD assembly file. This will be linked as +# the first object file, so it will appear at address 0 +HEAD_ASRC = qemu_rv32_head.S + +# Specify our general Assembly files +CHIP_ASRCS = qemu_rv32_vectors.S riscv_syscall.S + +# Specify C code within the common directory to be included +CMN_CSRCS += riscv_initialize.c riscv_swint.c +CMN_CSRCS += riscv_allocateheap.c riscv_createstack.c riscv_exit.c +CMN_CSRCS += riscv_assert.c riscv_blocktask.c riscv_copystate.c riscv_initialstate.c +CMN_CSRCS += riscv_interruptcontext.c riscv_modifyreg32.c riscv_puts.c +CMN_CSRCS += riscv_releasepending.c riscv_reprioritizertr.c riscv_copyfullstate.c +CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c +CMN_CSRCS += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c + +ifeq ($(CONFIG_STACK_COLORATION),y) +CMN_CSRCS += riscv_checkstack.c +endif + +ifeq ($(CONFIG_ARCH_HAVE_VFORK),y) +CMN_CSRCS += riscv_vfork.c +endif + +# Specify our C code within this directory to be included +CHIP_CSRCS = qemu_rv32_start.c qemu_rv32_irq_dispatch.c qemu_rv32_irq.c +CHIP_CSRCS += qemu_rv32_idle.c qemu_rv32_timerisr.c diff --git a/arch/risc-v/src/qemu-rv32/chip.h b/arch/risc-v/src/qemu-rv32/chip.h new file mode 100644 index 0000000000..583c588ae3 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/chip.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_QEMU_RV32_CHIP_H +#define __ARCH_RISCV_SRC_QEMU_RV32_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include the chip capabilities file */ + +#include + +#ifndef __ASSEMBLY__ + +/* Include the chip interrupt definition file */ + +/* Serial initial function defined in uart_16550.c */ + +extern void up_earlyserialinit(void); +extern void up_serialinit(void); + +#endif + +#include "qemu_rv32_memorymap.h" + +#endif /* __ARCH_RISCV_SRC_QEMU_RV32_CHIP_H */ diff --git a/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_clint.h b/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_clint.h new file mode 100644 index 0000000000..89a5a84bd0 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_clint.h @@ -0,0 +1,31 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_clint.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_QEMU_RV32_HARDWARE_QEMU_RV32_CLINT_H +#define __ARCH_RISCV_SRC_QEMU_RV32_HARDWARE_QEMU_RV32_CLINT_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define QEMU_RV32_CLINT_MTIMECMP (QEMU_RV32_CLINT_BASE + 0x4000) +#define QEMU_RV32_CLINT_MTIME (QEMU_RV32_CLINT_BASE + 0xbff8) + +#endif /* __ARCH_RISCV_SRC_QEMU_RV32_HARDWARE_QEMU_RV32_CLINT_H */ diff --git a/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_memorymap.h b/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_memorymap.h new file mode 100644 index 0000000000..72a03e0164 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_memorymap.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_QEMU_RV32_HARDWARE_QEMU_RV32_MEMORYMAP_H +#define __ARCH_RISCV_SRC_QEMU_RV32_HARDWARE_QEMU_RV32_MEMORYMAP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Base Address ****************************************************/ + +#define QEMU_RV32_CLINT_BASE 0x02000000 +#define QEMU_RV32_PLIC_BASE 0x0c000000 + +#endif /* __ARCH_RISCV_SRC_QEMU_RV32_HARDWARE_QEMU_RV32_MEMORYMAP_H */ diff --git a/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_plic.h b/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_plic.h new file mode 100644 index 0000000000..83b9b26943 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_plic.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/hardware/qemu_rv32_plic.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_FE310_HARDWARE_FE310_PLIC_H +#define __ARCH_RISCV_SRC_FE310_HARDWARE_FE310_PLIC_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define QEMU_RV32_PLIC_PRIORITY (QEMU_RV32_PLIC_BASE + 0x000000) +#define QEMU_RV32_PLIC_PENDING1 (QEMU_RV32_PLIC_BASE + 0x001000) +#define QEMU_RV32_PLIC_ENABLE1 (QEMU_RV32_PLIC_BASE + 0x002000) +#define QEMU_RV32_PLIC_ENABLE2 (QEMU_RV32_PLIC_BASE + 0x002004) +#define QEMU_RV32_PLIC_THRESHOLD (QEMU_RV32_PLIC_BASE + 0x200000) +#define QEMU_RV32_PLIC_CLAIM (QEMU_RV32_PLIC_BASE + 0x200004) + +#endif /* __ARCH_RISCV_SRC_FE310_HARDWARE_FE310_PLIC_H */ diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_head.S b/arch/risc-v/src/qemu-rv32/qemu_rv32_head.S new file mode 100644 index 0000000000..6e3a0b97d0 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_head.S @@ -0,0 +1,227 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_head.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + /* Exported Symbols */ + + .global exception_common + .global __start + + .section .text + +__start: + + /* Set stack pointer to the idle thread stack */ + + lui sp, %hi(QEMU_RV32_IDLESTACK_TOP) + addi sp, sp, %lo(QEMU_RV32_IDLESTACK_TOP) + + csrw mie, zero + + la t0, __trap_vec + csrw mtvec, t0 + + /* Jump to qemu_rv32_start */ + + jal x1, qemu_rv32_start + + /* We shouldn't return from _start */ + + .global _init + .global _fini + +_init: +_fini: + + /* These don't have to do anything since we use init_array/fini_array. */ + + ret + +/**************************************************************************** + * Name: exception_common + ****************************************************************************/ + +exception_common: + + addi sp, sp, -XCPTCONTEXT_SIZE + + sw x1, 1*4(sp) /* ra */ + sw x3, 3*4(sp) /* gp */ + sw x4, 4*4(sp) /* tp */ + sw x5, 5*4(sp) /* t0 */ + sw x6, 6*4(sp) /* t1 */ + sw x7, 7*4(sp) /* t2 */ + sw x8, 8*4(sp) /* s0 */ + sw x9, 9*4(sp) /* s1 */ + sw x10, 10*4(sp) /* a0 */ + sw x11, 11*4(sp) /* a1 */ + sw x12, 12*4(sp) /* a2 */ + sw x13, 13*4(sp) /* a3 */ + sw x14, 14*4(sp) /* a4 */ + sw x15, 15*4(sp) /* a5 */ + sw x16, 16*4(sp) /* a6 */ + sw x17, 17*4(sp) /* a7 */ + sw x18, 18*4(sp) /* s2 */ + sw x19, 19*4(sp) /* s3 */ + sw x20, 20*4(sp) /* s4 */ + sw x21, 21*4(sp) /* s5 */ + sw x22, 22*4(sp) /* s6 */ + sw x23, 23*4(sp) /* s7 */ + sw x24, 24*4(sp) /* s8 */ + sw x25, 25*4(sp) /* s9 */ + sw x26, 26*4(sp) /* s10 */ + sw x27, 27*4(sp) /* s11 */ + sw x28, 28*4(sp) /* t3 */ + sw x29, 29*4(sp) /* t4 */ + sw x30, 30*4(sp) /* t5 */ + sw x31, 31*4(sp) /* t6 */ + +#if defined(INT_XCPT_REGS) && INT_XCPT_REGS >= 39 + csrr x28, 0x7b0 + csrr x29, 0x7b1 + csrr x30, 0x7b2 + sw x28, 33*4(sp) + sw x29, 34*4(sp) + sw x30, 35*4(sp) + csrr x28, 0x7b4 + csrr x29, 0x7b5 + csrr x30, 0x7b6 + sw x28, 36*4(sp) + sw x29, 37*4(sp) + sw x30, 38*4(sp) +#endif + + csrr s0, mstatus + sw s0, 32*4(sp) /* mstatus */ + + addi s0, sp, XCPTCONTEXT_SIZE + sw s0, 2*4(sp) /* original SP */ + + /* Setup arg0(exception cause), arg1(context) */ + + csrr a0, mcause /* exception cause */ + csrr s0, mepc + sw s0, 0(sp) /* exception PC */ + + mv a1, sp /* context = sp */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 + /* Switch to interrupt stack */ + + lui sp, %hi(g_intstacktop) + addi sp, sp, %lo(g_intstacktop) +#endif + + /* Call interrupt handler in C */ + + jal x1, qemu_rv32_dispatch_irq + + /* If context switch is needed, return a new sp */ + + mv sp, a0 + lw s0, 0(sp) /* restore mepc */ + csrw mepc, s0 + + lw s0, 32*4(sp) /* restore mstatus */ + csrw mstatus, s0 + +#if defined(INT_XCPT_REGS) && INT_XCPT_REGS >= 39 + lw x28, 36*4(sp) + lw x29, 37*4(sp) + lw x30, 38*4(sp) + csrrw x0, 0x7b4, x28 + csrrw x0, 0x7b5, x29 + csrrw x0, 0x7b6, x30 + lw x28, 33*4(sp) + lw x29, 34*4(sp) + lw x30, 35*4(sp) + csrrw x0, 0x7b0, x28 + csrrw x0, 0x7b1, x29 + csrrw x0, 0x7b2, x30 +#endif + + lw x3, 3*4(sp) /* gp */ + lw x4, 4*4(sp) /* tp */ + lw x5, 5*4(sp) /* t0 */ + lw x6, 6*4(sp) /* t1 */ + lw x7, 7*4(sp) /* t2 */ + lw x8, 8*4(sp) /* s0 */ + lw x9, 9*4(sp) /* s1 */ + lw x10, 10*4(sp) /* a0 */ + lw x11, 11*4(sp) /* a1 */ + lw x12, 12*4(sp) /* a2 */ + lw x13, 13*4(sp) /* a3 */ + lw x14, 14*4(sp) /* a4 */ + lw x15, 15*4(sp) /* a5 */ + lw x16, 16*4(sp) /* a6 */ + lw x17, 17*4(sp) /* a7 */ + lw x18, 18*4(sp) /* s2 */ + lw x19, 19*4(sp) /* s3 */ + lw x20, 20*4(sp) /* s4 */ + lw x21, 21*4(sp) /* s5 */ + lw x22, 22*4(sp) /* s6 */ + lw x23, 23*4(sp) /* s7 */ + lw x24, 24*4(sp) /* s8 */ + lw x25, 25*4(sp) /* s9 */ + lw x26, 26*4(sp) /* s10 */ + lw x27, 27*4(sp) /* s11 */ + lw x28, 28*4(sp) /* t3 */ + lw x29, 29*4(sp) /* t4 */ + lw x30, 30*4(sp) /* t5 */ + lw x31, 31*4(sp) /* t6 */ + + lw x1, 1*4(sp) /* ra */ + + lw sp, 2*4(sp) /* restore original sp */ + + /* Return from Machine Interrupt */ + + mret + +/******************************************************************************* + * Name: g_intstackalloc and g_intstacktop +*******************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 + .bss + .balign 16 + .global g_intstackalloc + .global g_intstacktop + .type g_intstackalloc, object + .type g_intstacktop, object +g_intstackalloc: + .skip ((CONFIG_ARCH_INTERRUPTSTACK + 8) & ~15) +g_intstacktop: + .skip 4 + .size g_intstacktop, 4 + .size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~15) +#endif diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_idle.c b/arch/risc-v/src/qemu-rv32/qemu_rv32_idle.c new file mode 100644 index 0000000000..e5db63c5f8 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_idle.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_idle.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "riscv_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when there is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + nxsched_process_timer(); +#else + + board_autoled_off(LED_CPU); + + /* This would be an appropriate place to put some MCU-specific logic to + * sleep in a reduced power mode until an interrupt occurs to save power + */ + + asm("WFI"); + +#endif +} diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_irq.c b/arch/risc-v/src/qemu-rv32/qemu_rv32_irq.c new file mode 100644 index 0000000000..862e36b57c --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_irq.c @@ -0,0 +1,209 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_irq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "riscv_internal.h" +#include "riscv_arch.h" + +#include "hardware/qemu_rv32_memorymap.h" +#include "hardware/qemu_rv32_plic.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + /* Disable Machine interrupts */ + + up_irq_save(); + + /* Disable all global interrupts */ + + putreg32(0x0, QEMU_RV32_PLIC_ENABLE1); + putreg32(0x0, QEMU_RV32_PLIC_ENABLE2); + + /* Colorize the interrupt stack for debug purposes */ + +#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15 + size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~15); + riscv_stack_color((void *)&g_intstackalloc, intstack_size); +#endif + + /* Set priority for all global interrupts to 1 (lowest) */ + + int id; + + for (id = 1; id <= 52; id++) + { + putreg32(1, QEMU_RV32_PLIC_PRIORITY + 4 * id); + } + + /* Set irq threshold to 0 (permits all global interrupts) */ + + putreg32(0, QEMU_RV32_PLIC_THRESHOLD); + + /* currents_regs is non-NULL only while processing an interrupt */ + + g_current_regs = NULL; + + /* Attach the ecall interrupt handler */ + + irq_attach(QEMU_RV32_IRQ_ECALLM, riscv_swint, NULL); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + int extirq; + uint32_t oldstat; + + if (irq == QEMU_RV32_IRQ_MTIMER) + { + /* Read mstatus & clear machine timer interrupt enable in mie */ + + asm volatile("csrrc %0, mie, %1" + : "=r"(oldstat) + : "r"(MIE_MTIE)); + } + else if (irq > QEMU_RV32_IRQ_MEXT) + { + extirq = irq - QEMU_RV32_IRQ_MEXT; + + /* Clear enable bit for the irq */ + + if (0 <= extirq && extirq <= 63) + { + modifyreg32(QEMU_RV32_PLIC_ENABLE1 + (4 * (extirq / 32)), + 1 << (extirq % 32), 0); + } + else + { + ASSERT(false); + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + int extirq; + uint32_t oldstat; + + if (irq == QEMU_RV32_IRQ_MTIMER) + { + /* Read mstatus & set machine timer interrupt enable in mie */ + + asm volatile("csrrs %0, mie, %1" + : "=r"(oldstat) + : "r"(MIE_MTIE)); + } + else if (irq > QEMU_RV32_IRQ_MEXT) + { + extirq = irq - QEMU_RV32_IRQ_MEXT; + + /* Set enable bit for the irq */ + + if (0 <= extirq && extirq <= 63) + { + modifyreg32(QEMU_RV32_PLIC_ENABLE1 + (4 * (extirq / 32)), + 0, 1 << (extirq % 32)); + } + else + { + ASSERT(false); + } + } +} + +irqstate_t up_irq_enable(void) +{ + uint64_t oldstat; + +#if 1 + /* Enable MEIE (machine external interrupt enable) */ + + /* TODO: should move to up_enable_irq() */ + + asm volatile ("csrrs %0, mie, %1": "=r" (oldstat) : "r"(MIE_MEIE)); +#endif + + /* Read mstatus & set machine interrupt enable (MIE) in mstatus */ + + asm volatile ("csrrs %0, mstatus, %1": "=r" (oldstat) : "r"(MSTATUS_MIE)); + return oldstat; +} + +/**************************************************************************** + * Name: riscv_get_newintctx + * + * Description: + * Return initial mstatus when a task is created. + * + ****************************************************************************/ + +uint32_t riscv_get_newintctx(void) +{ + /* Set machine previous privilege mode to machine mode. + * Also set machine previous interrupt enable + */ + + return (MSTATUS_MPPM | MSTATUS_MPIE); +} diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_irq_dispatch.c b/arch/risc-v/src/qemu-rv32/qemu_rv32_irq_dispatch.c new file mode 100644 index 0000000000..467eb959db --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_irq_dispatch.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_irq_dispatch.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "riscv_arch.h" +#include "riscv_internal.h" + +#include "hardware/qemu_rv32_memorymap.h" +#include "hardware/qemu_rv32_plic.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint32_t * g_current_regs; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * qemu_rv32_dispatch_irq + ****************************************************************************/ + +void *qemu_rv32_dispatch_irq(uint32_t vector, uint32_t *regs) +{ + uint32_t irq = (vector >> 27) | (vector & 0xf); + uint32_t *mepc = regs; + + /* Firstly, check if the irq is machine external interrupt */ + + if (QEMU_RV32_IRQ_MEXT == irq) + { + uint32_t val = getreg32(QEMU_RV32_PLIC_CLAIM); + + /* Add the value to nuttx irq which is offset to the mext */ + + irq += val; + } + + /* NOTE: In case of ecall, we need to adjust mepc in the context */ + + if (QEMU_RV32_IRQ_ECALLM == irq) + { + *mepc += 4; + } + +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(); +#else + /* Current regs non-zero indicates that we are processing an interrupt; + * g_current_regs is also used to manage interrupt level context switches. + * + * Nested interrupts are not supported + */ + + DEBUGASSERT(g_current_regs == NULL); + g_current_regs = regs; + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + + if (QEMU_RV32_IRQ_MEXT <= irq) + { + /* Then write PLIC_CLAIM to clear pending in PLIC */ + + putreg32(irq - QEMU_RV32_IRQ_MEXT, QEMU_RV32_PLIC_CLAIM); + } +#endif + + /* If a context switch occurred while processing the interrupt then + * g_current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint32_t *)g_current_regs; + g_current_regs = NULL; + + return regs; +} diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_memorymap.h b/arch/risc-v/src/qemu-rv32/qemu_rv32_memorymap.h new file mode 100644 index 0000000000..4234912295 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_memorymap.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_QEMU_RV32_QEMU_RV32_MEMORYMAP_H +#define __ARCH_RISCV_SRC_QEMU_RV32_QEMU_RV32_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Idle thread stack starts from _ebss */ + +#ifndef __ASSEMBLY__ +#define QEMU_RV32_IDLESTACK_BASE (uint32_t)&_ebss +#else +#define QEMU_RV32_IDLESTACK_BASE _ebss +#endif + +#define QEMU_RV32_IDLESTACK_SIZE (CONFIG_IDLETHREAD_STACKSIZE & ~3) +#define QEMU_RV32_IDLESTACK_TOP (QEMU_RV32_IDLESTACK_BASE + QEMU_RV32_IDLESTACK_SIZE) + +#endif /* __ARCH_RISCV_SRC_QEMU_RV32_QEMU_RV32_MEMORYMAP_H */ diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_start.c b/arch/risc-v/src/qemu-rv32/qemu_rv32_start.c new file mode 100644 index 0000000000..a5bebb6580 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_start.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_start.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "riscv_internal.h" + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +#define showprogress(c) up_putc(c) +#else +#define showprogress(c) +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* NOTE: g_idle_topstack needs to point the top of the idle stack + * for CPU0 and this value is used in up_initial_state() + */ + +uint32_t g_idle_topstack = QEMU_RV32_IDLESTACK_TOP; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: qemu_rv32_start + ****************************************************************************/ + +void qemu_rv32_start(void) +{ + uint32_t *dest; + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = &_sbss; dest < &_ebss; ) + { + *dest++ = 0; + } + + showprogress('A'); + +#ifdef USE_EARLYSERIALINIT + up_earlyserialinit(); +#endif + + showprogress('B'); + + /* Do board initialization */ + + showprogress('C'); + + /* Call nx_start() */ + + nx_start(); + + while (true) + { + asm("WFI"); + } +} + +void riscv_serialinit(void) +{ + up_serialinit(); +} diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_timerisr.c b/arch/risc-v/src/qemu-rv32/qemu_rv32_timerisr.c new file mode 100644 index 0000000000..b9c7f0ea95 --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_timerisr.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * arch/risc-v/src/qemu-rv32/qemu_rv32_timerisr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "riscv_arch.h" + +#include "hardware/qemu_rv32_memorymap.h" +#include "hardware/qemu_rv32_clint.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define getreg64(a) (*(volatile uint64_t *)(a)) +#define putreg64(v,a) (*(volatile uint64_t *)(a) = (v)) + +#define TICK_COUNT (10000000 / TICK_PER_SEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static bool _b_tick_started = false; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: qemu_rv32_reload_mtimecmp + ****************************************************************************/ + +static void qemu_rv32_reload_mtimecmp(void) +{ + irqstate_t flags = spin_lock_irqsave(NULL); + + uint64_t current; + uint64_t next; + + if (!_b_tick_started) + { + _b_tick_started = true; + current = getreg64(QEMU_RV32_CLINT_MTIME); + } + else + { + current = getreg64(QEMU_RV32_CLINT_MTIMECMP); + } + + next = current + TICK_COUNT; + putreg64(next, QEMU_RV32_CLINT_MTIMECMP); + + spin_unlock_irqrestore(NULL, flags); +} + +/**************************************************************************** + * Name: qemu_rv32_timerisr + ****************************************************************************/ + +static int qemu_rv32_timerisr(int irq, void *context, void *arg) +{ + qemu_rv32_reload_mtimecmp(); + + /* Process timer interrupt */ + + nxsched_process_timer(); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + /* Attach timer interrupt handler */ + + irq_attach(QEMU_RV32_IRQ_MTIMER, qemu_rv32_timerisr, NULL); + + /* Reload CLINT mtimecmp */ + + qemu_rv32_reload_mtimecmp(); + + /* And enable the timer interrupt */ + + up_enable_irq(QEMU_RV32_IRQ_MTIMER); +} diff --git a/arch/risc-v/src/qemu-rv32/qemu_rv32_vectors.S b/arch/risc-v/src/qemu-rv32/qemu_rv32_vectors.S new file mode 100644 index 0000000000..27fb8ac3bc --- /dev/null +++ b/arch/risc-v/src/qemu-rv32/qemu_rv32_vectors.S @@ -0,0 +1,34 @@ +/**************************************************************************** + * arch/risc-v/src/fe310/fe310_vectors.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + + .section .text.vec + .global __trap_vec + +/**************************************************************************** + * Name: exception_common + ****************************************************************************/ + +__trap_vec: + j exception_common + nop diff --git a/boards/Kconfig b/boards/Kconfig index 3c9700f7f2..6b5e655eef 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1443,6 +1443,13 @@ config ARCH_BOARD_RV32M1_VEGA This is the board configuration for the port of NuttX to the RV32M1 VEGA board. This board features the RV32M1 RISC-V Core(s). +config ARCH_BOARD_QEMU_RV32_VIRT + bool "QEMU RV32 Virt" + depends on ARCH_CHIP_QEMU_RV32 + ---help--- + This is the board configuration for the port of NuttX to the + QEMU RV32 Virt board. This board features the QEMU RV32 CPU. + config ARCH_BOARD_S32K118EVB bool "NXP S32K118EVB" depends on ARCH_CHIP_S32K118 @@ -2490,6 +2497,7 @@ config ARCH_BOARD default "s32k144evb" if ARCH_BOARD_S32K144EVB default "ucans32k146" if ARCH_BOARD_UCANS32K146 default "rv32m1-vega" if ARCH_BOARD_RV32M1_VEGA + default "rv32-virt" if ARCH_BOARD_QEMU_RV32_VIRT default "s32k146evb" if ARCH_BOARD_S32K146EVB default "s32k148evb" if ARCH_BOARD_S32K148EVB default "sabre-6quad" if ARCH_BOARD_SABRE_6QUAD @@ -3234,6 +3242,9 @@ endif if ARCH_BOARD_RV32M1_VEGA source "boards/risc-v/rv32m1/rv32m1-vega/Kconfig" endif +if ARCH_BOARD_QEMU_RV32_VIRT +source "boards/risc-v/qemu-rv32/rv32-virt/Kconfig" +endif if ARCH_BOARD_ESP32C3_DEVKIT source "boards/risc-v/esp32c3/esp32c3-devkit/Kconfig" endif diff --git a/boards/risc-v/qemu-rv32/rv32-virt/Kconfig b/boards/risc-v/qemu-rv32/rv32-virt/Kconfig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/boards/risc-v/qemu-rv32/rv32-virt/README.txt b/boards/risc-v/qemu-rv32/rv32-virt/README.txt new file mode 100644 index 0000000000..2b22818e28 --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/README.txt @@ -0,0 +1,31 @@ +1. Download and install toolchain + + $ curl https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz + +2. Build and install qemu + + $ git clone https://github.com/qemu/qemu + $ cd qemu + $ ./configure --target-list=riscv32-softmmu + $ make + $ sudo make install + +3. Configure and build NuttX + + $ mkdir ./nuttx; cd ./nuttx + $ git clone https://github.com/apache/incubator-nuttx.git + $ git clone https://github.com/apache/incubator-nuttx-apps.git + $ cd nuttx + $ make distclean + $ ./tools/configure.sh rv32-virt:nsh + $ make + +4. Run the nuttx with qemu + + $ qemu-system-riscv32 -M virt -cpu rv32 -bios none -kernel nuttx -nographic + +5. TODO + + Support FPU + Support RISC-V User mode + Support Network diff --git a/boards/risc-v/qemu-rv32/rv32-virt/configs/nsh/defconfig b/boards/risc-v/qemu-rv32/rv32-virt/configs/nsh/defconfig new file mode 100644 index 0000000000..3190576b46 --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/configs/nsh/defconfig @@ -0,0 +1,66 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLE_CAT is not set +# CONFIG_NSH_DISABLE_CD is not set +# CONFIG_NSH_DISABLE_FREE is not set +# CONFIG_NSH_DISABLE_HELP is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_NSH_DISABLE_LS is not set +# CONFIG_NSH_DISABLE_MOUNT is not set +# CONFIG_NSH_DISABLE_UNAME is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_PSSTACKUSAGE is not set +CONFIG_16550_ADDRWIDTH=32 +CONFIG_16550_UART0=y +CONFIG_16550_UART0_BASE=0x10000000 +CONFIG_16550_UART0_CLOCK=3686400 +CONFIG_16550_UART0_IRQ=37 +CONFIG_16550_UART0_SERIAL_CONSOLE=y +CONFIG_16550_UART=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="rv32-virt" +CONFIG_ARCH_BOARD_QEMU_RV32_VIRT=y +CONFIG_ARCH_CHIP="qemu-rv32" +CONFIG_ARCH_CHIP_QEMU_RV32=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BINFMT_DISABLE=y +CONFIG_BOARD_LOOPSPERMSEC=6366 +CONFIG_BUILTIN=y +CONFIG_CLOCK_MONOTONIC=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_ZERO=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=64 +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RAM_SIZE=33554432 +CONFIG_RAM_START=0x80000000 +CONFIG_RR_INTERVAL=200 +CONFIG_RV32IM_HW_MULDIV=y +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_UART_ARCH_MMIO=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2021 +CONFIG_SYSTEM_NSH=y +CONFIG_USEC_PER_TICK=1000 +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/boards/risc-v/qemu-rv32/rv32-virt/include/board.h b/boards/risc-v/qemu-rv32/rv32-virt/include/board.h new file mode 100644 index 0000000000..753d4f2c67 --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/include/board.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * boards/risc-v/qemu-rv32/rv32-virt/include/board.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_QEMU_RV32_RV32_VIRT_INCLUDE_BOARD_H +#define __BOARDS_RISCV_QEMU_RV32_RV32_VIRT_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LED_STARTED 0 /* N/A */ +#define LED_HEAPALLOCATE 1 /* N/A */ +#define LED_IRQSENABLED 2 /* N/A */ +#define LED_STACKCREATED 3 /* N/A */ +#define LED_INIRQ 4 /* N/A */ +#define LED_SIGNAL 5 /* N/A */ +#define LED_ASSERTION 6 /* N/A */ +#define LED_PANIC 7 /* N/A */ +#define LED_CPU 8 /* LED */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: qemu_rv32_boardinitialize + ****************************************************************************/ + +void qemu_rv32_boardinitialize(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_QEMU_RV32_RV32_VIRT_INCLUDE_BOARD_H */ diff --git a/boards/risc-v/qemu-rv32/rv32-virt/include/nsh_romfsimg.h b/boards/risc-v/qemu-rv32/rv32-virt/include/nsh_romfsimg.h new file mode 100644 index 0000000000..6264fcc3ec --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/include/nsh_romfsimg.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * boards/risc-v/qemu-rv32/rv32-virt/include/nsh_romfsimg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_QEMU_RV32_RV32_VIRT_INCLUDE_NSH_ROMFSIMG_H +#define __BOARDS_RISCV_QEMU_RV32_RV32_VIRT_INCLUDE_NSH_ROMFSIMG_H +extern const unsigned char romfs_img[]; +extern const unsigned int romfs_img_len; +#endif diff --git a/boards/risc-v/qemu-rv32/rv32-virt/scripts/Make.defs b/boards/risc-v/qemu-rv32/rv32-virt/scripts/Make.defs new file mode 100644 index 0000000000..cb8f0276cc --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/scripts/Make.defs @@ -0,0 +1,64 @@ +############################################################################ +# boards/risc-v/rv32m1/rv32m1-vega/scripts/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/risc-v/src/rv32im/Toolchain.defs + +ifeq ($(CONFIG_ARCH_CHIP_QEMU_RV32),y) + LDSCRIPT = ld.script +endif + +ifeq ($(CONFIG_CYGWIN_WINTOOL),y) + ARCHSCRIPT = -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)}" +else + ARCHSCRIPT = -T$(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) +endif + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g + ASARCHCPUFLAGS += -Wa,-g +endif + +MAXOPTIMIZATION = -Os + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +ARCHCPUFLAGS = -march=rv32imc -mabi=ilp32 +ARCHCFLAGS = -fno-builtin -ffunction-sections -fdata-sections +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHPICFLAGS = -fpic -msingle-pic-base + +CFLAGS := $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS += $(CFLAGS) -D__ASSEMBLY__ $(ASARCHCPUFLAGS) + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +LDFLAGS += --gc-sections -melf32lriscv diff --git a/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script b/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script new file mode 100644 index 0000000000..929e66c14e --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script @@ -0,0 +1,119 @@ +/**************************************************************************** + * boards/risc-v/qemu-rv32/rv32-virt/scripts/ld.script + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +SECTIONS +{ + . = 0x80000000; + + .text : + { + _stext = . ; + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.jcr) + + /* C++ support: The .init and .fini sections contain specific logic + * to manage static constructors and destructors. + */ + + *(.gnu.linkonce.t.*) + *(.init) /* Old ABI */ + *(.fini) /* Old ABI */ + _etext = . ; + } + + .rodata : + { + _srodata = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + _erodata = . ; + } + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = . ; + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + . = ALIGN(4); + _edata = . ; + } + + /* C++ support. For each global and static local C++ object, + * GCC creates a small subroutine to construct the object. Pointers + * to these routines (not the routines themselves) are stored as + * simple, linear arrays in the .ctors section of the object file. + * Similarly, pointers to global/static destructor routines are + * stored in .dtors. + */ + + .ctors : + { + _sctors = . ; + *(.ctors) /* Old ABI: Unallocated */ + *(.init_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .dtors : + { + _sdtors = . ; + *(.dtors) /* Old ABI: Unallocated */ + *(.fini_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .bss : + { + _sbss = . ; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + _ebss = . ; + } + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/risc-v/qemu-rv32/rv32-virt/src/.gitignore b/boards/risc-v/qemu-rv32/rv32-virt/src/.gitignore new file mode 100644 index 0000000000..cc92d189b5 --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/src/.gitignore @@ -0,0 +1,2 @@ +etctmp +etctmp.c diff --git a/boards/risc-v/qemu-rv32/rv32-virt/src/Makefile b/boards/risc-v/qemu-rv32/rv32-virt/src/Makefile new file mode 100644 index 0000000000..debf575cf5 --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/src/Makefile @@ -0,0 +1,27 @@ +############################################################################ +# boards/risc-v/rv32m1/rv32m1-vega/src/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +RCSRCS = etc/init.d/rcS + +CSRCS = qemu_rv32_appinit.c + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/risc-v/qemu-rv32/rv32-virt/src/etc/init.d/rcS b/boards/risc-v/qemu-rv32/rv32-virt/src/etc/init.d/rcS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/boards/risc-v/qemu-rv32/rv32-virt/src/qemu_rv32_appinit.c b/boards/risc-v/qemu-rv32/rv32-virt/src/qemu_rv32_appinit.c new file mode 100644 index 0000000000..7468051d19 --- /dev/null +++ b/boards/risc-v/qemu-rv32/rv32-virt/src/qemu_rv32_appinit.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * boards/risc-v/qemu-rv32/rv32-virt/src/qemu_rv32_appinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform architecture specific initialization + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value could be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ +#ifdef CONFIG_BOARD_LATE_INITIALIZE + /* Board initialization already performed by board_late_initialize() */ + + return OK; +#else + /* Perform board-specific initialization */ + +#ifdef CONFIG_NSH_ARCHINIT + + mount(NULL, "/proc", "procfs", 0, NULL); + +#endif + + return OK; +#endif +}