From 0b35d45b2cdb25beb396cc7f8ce8457d65d94272 Mon Sep 17 00:00:00 2001 From: Afonso Oliveira Date: Mon, 21 Sep 2026 20:57:59 +0100 Subject: [PATCH] riscv/erbium: Add standalone Minion emulator support. Add an initial port for the AIFoundry Erbium Minion core running on the public ET-platform system emulator (erbium_emu). NuttX boots directly from a firmware ELF at 0x40000200, runs in machine mode on hart 0 with SMP disabled, and parks secondary harts before they touch memory. The chip layer provides startup, PLIC interrupts, the UART0 console driver and the machine timer. Context switching, FPU save/restore, heap, idle and timer handling reuse the common RISC-V code. Atomics use interrupt masking because the core does not implement the A extension. Erbium implements the F extension but executes fdiv/fsqrt and FENCE.I in microcode, which a standalone image does not provide. The board build files pass -mno-fdiv to GCC when the FPU is enabled, so those operations use software helpers. Startup initializes the FPU without the common FENCE.I sequence, and the board configurations disable the dynamic ELF loader, which also relies on FENCE.I. Add minion:nsh and minion:ostest configurations, Make and CMake support, CMake CI build entries, and a host script that runs prebuilt images in the emulator and checks the console and OS test results. Tested with emulator revision 836a4ab600e9 and xPack GCC 14.3.0: both configurations build with Make and CMake, ostest exits with status 0 including the FPU tests, and the NSH console, procfs, timer and UART receive paths work. Silicon, SMP, protected builds and reboot are not covered by this initial port. Signed-off-by: Afonso Oliveira --- arch/risc-v/Kconfig | 21 + arch/risc-v/include/erbium/chip.h | 26 + arch/risc-v/include/erbium/irq.h | 35 + arch/risc-v/src/erbium/CMakeLists.txt | 26 + arch/risc-v/src/erbium/Kconfig | 22 + arch/risc-v/src/erbium/Make.defs | 28 + arch/risc-v/src/erbium/chip.h | 42 + arch/risc-v/src/erbium/erbium_head.S | 97 +++ arch/risc-v/src/erbium/erbium_irq.c | 166 ++++ arch/risc-v/src/erbium/erbium_irq_dispatch.c | 83 ++ arch/risc-v/src/erbium/erbium_memorymap.h | 45 ++ arch/risc-v/src/erbium/erbium_serial.c | 755 ++++++++++++++++++ arch/risc-v/src/erbium/erbium_start.c | 79 ++ arch/risc-v/src/erbium/erbium_timerisr.c | 68 ++ .../src/erbium/hardware/erbium_memorymap.h | 36 + .../src/erbium/hardware/erbium_mtimer.h | 40 + arch/risc-v/src/erbium/hardware/erbium_plic.h | 45 ++ .../src/erbium/hardware/erbium_sysreg.h | 39 + arch/risc-v/src/erbium/hardware/erbium_uart.h | 48 ++ boards/Kconfig | 11 + boards/risc-v/erbium/minion/CMakeLists.txt | 23 + boards/risc-v/erbium/minion/Kconfig | 10 + .../erbium/minion/cmake/Toolchain.cmake | 28 + .../erbium/minion/configs/nsh/defconfig | 48 ++ .../erbium/minion/configs/ostest/defconfig | 45 ++ boards/risc-v/erbium/minion/include/board.h | 35 + boards/risc-v/erbium/minion/scripts/Make.defs | 47 ++ boards/risc-v/erbium/minion/scripts/ld.script | 126 +++ .../risc-v/erbium/minion/src/CMakeLists.txt | 27 + boards/risc-v/erbium/minion/src/Makefile | 27 + .../risc-v/erbium/minion/src/erbium_bringup.c | 67 ++ boards/risc-v/erbium/minion/tools/test_emu.py | 199 +++++ tools/ci/testlist/risc-v-01.dat | 4 + 33 files changed, 2398 insertions(+) create mode 100644 arch/risc-v/include/erbium/chip.h create mode 100644 arch/risc-v/include/erbium/irq.h create mode 100644 arch/risc-v/src/erbium/CMakeLists.txt create mode 100644 arch/risc-v/src/erbium/Kconfig create mode 100644 arch/risc-v/src/erbium/Make.defs create mode 100644 arch/risc-v/src/erbium/chip.h create mode 100644 arch/risc-v/src/erbium/erbium_head.S create mode 100644 arch/risc-v/src/erbium/erbium_irq.c create mode 100644 arch/risc-v/src/erbium/erbium_irq_dispatch.c create mode 100644 arch/risc-v/src/erbium/erbium_memorymap.h create mode 100644 arch/risc-v/src/erbium/erbium_serial.c create mode 100644 arch/risc-v/src/erbium/erbium_start.c create mode 100644 arch/risc-v/src/erbium/erbium_timerisr.c create mode 100644 arch/risc-v/src/erbium/hardware/erbium_memorymap.h create mode 100644 arch/risc-v/src/erbium/hardware/erbium_mtimer.h create mode 100644 arch/risc-v/src/erbium/hardware/erbium_plic.h create mode 100644 arch/risc-v/src/erbium/hardware/erbium_sysreg.h create mode 100644 arch/risc-v/src/erbium/hardware/erbium_uart.h create mode 100644 boards/risc-v/erbium/minion/CMakeLists.txt create mode 100644 boards/risc-v/erbium/minion/Kconfig create mode 100644 boards/risc-v/erbium/minion/cmake/Toolchain.cmake create mode 100644 boards/risc-v/erbium/minion/configs/nsh/defconfig create mode 100644 boards/risc-v/erbium/minion/configs/ostest/defconfig create mode 100644 boards/risc-v/erbium/minion/include/board.h create mode 100644 boards/risc-v/erbium/minion/scripts/Make.defs create mode 100644 boards/risc-v/erbium/minion/scripts/ld.script create mode 100644 boards/risc-v/erbium/minion/src/CMakeLists.txt create mode 100644 boards/risc-v/erbium/minion/src/Makefile create mode 100644 boards/risc-v/erbium/minion/src/erbium_bringup.c create mode 100644 boards/risc-v/erbium/minion/tools/test_emu.py diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 3e4eec577da..8b769e9b059 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -264,6 +264,23 @@ config ARCH_CHIP_C906 ---help--- THEAD C906 processor (RISC-V 64bit core with GCVX extensions). +config ARCH_CHIP_ERBIUM + bool "AIFoundry Erbium" + select ARCH_RV64 + select ARCH_RV_ISA_M + select ARCH_RV_ISA_C + select ARCH_HAVE_FPU + select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION + select ALARM_ARCH + select LIBC_ATOMIC_IRQ + select OTHER_UART_SERIALDRIVER + select UART0_SERIALDRIVER + ---help--- + AIFoundry Erbium minion hart: RV64IMFC, machine timer, + and SiFive-style PLIC. + config ARCH_CHIP_MPFS bool "MicroChip Polarfire (MPFS)" select ARCH_RV64 @@ -672,6 +689,7 @@ config ARCH_CHIP default "esp32h2" if ARCH_CHIP_ESP32H2 default "esp32p4" if ARCH_CHIP_ESP32P4 default "c906" if ARCH_CHIP_C906 + default "erbium" if ARCH_CHIP_ERBIUM default "mpfs" if ARCH_CHIP_MPFS default "rv32m1" if ARCH_CHIP_RV32M1 default "qemu-rv" if ARCH_CHIP_QEMU_RV @@ -930,6 +948,9 @@ endif if ARCH_CHIP_C906 source "arch/risc-v/src/c906/Kconfig" endif +if ARCH_CHIP_ERBIUM +source "arch/risc-v/src/erbium/Kconfig" +endif if ARCH_CHIP_MPFS source "arch/risc-v/src/mpfs/Kconfig" endif diff --git a/arch/risc-v/include/erbium/chip.h b/arch/risc-v/include/erbium/chip.h new file mode 100644 index 00000000000..a2f0fd8419e --- /dev/null +++ b/arch/risc-v/include/erbium/chip.h @@ -0,0 +1,26 @@ +/**************************************************************************** + * arch/risc-v/include/erbium/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_CHIP_H +#define __ARCH_RISCV_INCLUDE_ERBIUM_CHIP_H + +#endif /* __ARCH_RISCV_INCLUDE_ERBIUM_CHIP_H */ diff --git a/arch/risc-v/include/erbium/irq.h b/arch/risc-v/include/erbium/irq.h new file mode 100644 index 00000000000..50c13cc3b46 --- /dev/null +++ b/arch/risc-v/include/erbium/irq.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * arch/risc-v/include/erbium/irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_IRQ_H +#define __ARCH_RISCV_INCLUDE_ERBIUM_IRQ_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERBIUM_IRQ_UART0 (RISCV_IRQ_MEXT + 3) +#define ERBIUM_IRQ_EXT_MAX (RISCV_IRQ_MEXT + 6) + +#define NR_IRQS (ERBIUM_IRQ_EXT_MAX + 1) + +#endif /* __ARCH_RISCV_INCLUDE_ERBIUM_IRQ_H */ diff --git a/arch/risc-v/src/erbium/CMakeLists.txt b/arch/risc-v/src/erbium/CMakeLists.txt new file mode 100644 index 00000000000..492a1c1d988 --- /dev/null +++ b/arch/risc-v/src/erbium/CMakeLists.txt @@ -0,0 +1,26 @@ +# ############################################################################## +# arch/risc-v/src/erbium/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +set(SRCS erbium_head.S erbium_start.c erbium_irq.c erbium_irq_dispatch.c + erbium_timerisr.c erbium_serial.c) + +target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/risc-v/src/erbium/Kconfig b/arch/risc-v/src/erbium/Kconfig new file mode 100644 index 00000000000..de2f898d1c7 --- /dev/null +++ b/arch/risc-v/src/erbium/Kconfig @@ -0,0 +1,22 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config ERBIUM_UART_CLOCK + int "UART input clock (Hz)" + default 6666667 + range 1 2147483647 + ---help--- + UART peripheral clock after the Erbium divide-by-30 prescaler, + with a 200 MHz system clock. + +config ERBIUM_MTIMER_FREQ + int "Machine timer frequency (Hz)" + default 2000000 + range 1 2147483647 + ---help--- + Machine timer frequency after the reference clock divider and + timer prescaler. The ET-platform emulator defaults to 2 MHz. diff --git a/arch/risc-v/src/erbium/Make.defs b/arch/risc-v/src/erbium/Make.defs new file mode 100644 index 00000000000..b4657dfee5a --- /dev/null +++ b/arch/risc-v/src/erbium/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# arch/risc-v/src/erbium/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 common/Make.defs + +HEAD_ASRC = erbium_head.S + +CHIP_CSRCS = erbium_start.c erbium_irq_dispatch.c erbium_irq.c +CHIP_CSRCS += erbium_timerisr.c erbium_serial.c diff --git a/arch/risc-v/src/erbium/chip.h b/arch/risc-v/src/erbium/chip.h new file mode 100644 index 00000000000..f90405b10c6 --- /dev/null +++ b/arch/risc-v/src/erbium/chip.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_CHIP_H +#define __ARCH_RISCV_SRC_ERBIUM_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "erbium_memorymap.h" +#include "hardware/erbium_memorymap.h" +#include "hardware/erbium_mtimer.h" +#include "hardware/erbium_plic.h" +#include "hardware/erbium_sysreg.h" +#include "riscv_internal.h" +#include "riscv_percpu.h" + +#endif /* __ARCH_RISCV_SRC_ERBIUM_CHIP_H */ diff --git a/arch/risc-v/src/erbium/erbium_head.S b/arch/risc-v/src/erbium/erbium_head.S new file mode 100644 index 00000000000..faf674ce562 --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_head.S @@ -0,0 +1,97 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_head.S + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "chip.h" +#include "riscv_macros.S" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: __start + * + * Description: + * Initialize the stack, global pointer and trap vector on hart 0 before + * entering C startup. Park other harts with their interrupts disabled. + * + * Input Parameters: + * None. + * + * Returned Value: + * Does not return. + * + ****************************************************************************/ + + .section .text.__start, "ax", @progbits + .global __start + .type __start, function + +__start: + csrw CSR_MIE, zero + csrr a0, CSR_MHARTID + bnez a0, 2f + + /* Only hart 0 owns the NuttX image and its stack. */ + + .option push + .option norelax + la gp, __global_pointer$ + .option pop + + riscv_set_inital_sp ERBIUM_IDLESTACK_BASE, SMP_STACK_SIZE, a0 + la t0, __erbium_trap_vec + csrw CSR_MTVEC, t0 + j erbium_start + +2: + wfi + j 2b + +/**************************************************************************** + * Name: __erbium_trap_vec + * + * Description: + * Transfer control to the common RISC-V exception entry point. + * + * Input Parameters: + * None. Hardware supplies the trap state in the machine CSRs. + * + * Returned Value: + * Returns through the common exception handler. + * + ****************************************************************************/ + + .section .text.exceptions, "ax", @progbits + .balign 4 + .global __erbium_trap_vec + +__erbium_trap_vec: + j exception_common diff --git a/arch/risc-v/src/erbium/erbium_irq.c b/arch/risc-v/src/erbium/erbium_irq.c new file mode 100644 index 00000000000..da82ccba70a --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_irq.c @@ -0,0 +1,166 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_irq.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "chip.h" +#include "riscv_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + * + * Description: + * Initialize hart 0 interrupt state and PLIC priorities, attach the + * common exception handlers, and enable interrupts unless suppressed. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_irqinitialize(void) +{ + int id; + + up_irq_save(); + WRITE_CSR(CSR_IE, 0); + putreg32(0, ERBIUM_PLIC_ENABLE1); + +#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15 + riscv_stack_color(g_intstackalloc, CONFIG_ARCH_INTERRUPTSTACK & ~15); +#endif + + for (id = 1; id <= ERBIUM_PLIC_NDEV; id++) + { + putreg32(1, ERBIUM_PLIC_PRIORITY + 4 * id); + } + + putreg32(0, ERBIUM_PLIC_THRESHOLD); + riscv_exception_attach(); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Mask a supported hart-local interrupt or PLIC source. Ignore numbers + * that do not identify a supported interrupt. + * + * Input Parameters: + * irq - NuttX interrupt number to disable. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + if (irq == RISCV_IRQ_SOFT) + { + CLEAR_CSR(CSR_IE, IE_SIE); + } + else if (irq == RISCV_IRQ_TIMER) + { + CLEAR_CSR(CSR_IE, IE_TIE); + } + else if (irq == RISCV_IRQ_EXT) + { + CLEAR_CSR(CSR_IE, IE_EIE); + } + else if (irq > RISCV_IRQ_EXT && irq < NR_IRQS) + { + modifyreg32(ERBIUM_PLIC_ENABLE1, 1u << (irq - RISCV_IRQ_EXT), 0); + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Unmask a supported hart-local interrupt or PLIC source. Ignore numbers + * that do not identify a supported interrupt. + * + * Input Parameters: + * irq - NuttX interrupt number to enable. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + if (irq == RISCV_IRQ_SOFT) + { + SET_CSR(CSR_IE, IE_SIE); + } + else if (irq == RISCV_IRQ_TIMER) + { + SET_CSR(CSR_IE, IE_TIE); + } + else if (irq == RISCV_IRQ_EXT) + { + SET_CSR(CSR_IE, IE_EIE); + } + else if (irq > RISCV_IRQ_EXT && irq < NR_IRQS) + { + modifyreg32(ERBIUM_PLIC_ENABLE1, 0, 1u << (irq - RISCV_IRQ_EXT)); + } +} + +/**************************************************************************** + * Name: up_irq_enable + * + * Description: + * Enable machine external interrupt delivery and global interrupts. + * + * Input Parameters: + * None. + * + * Returned Value: + * The previous status register value, for restoring interrupt state. + * + ****************************************************************************/ + +irqstate_t up_irq_enable(void) +{ + up_enable_irq(RISCV_IRQ_EXT); + return READ_AND_SET_CSR(CSR_STATUS, STATUS_IE); +} diff --git a/arch/risc-v/src/erbium/erbium_irq_dispatch.c b/arch/risc-v/src/erbium/erbium_irq_dispatch.c new file mode 100644 index 00000000000..ecc6369cddf --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_irq_dispatch.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_irq_dispatch.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "hardware/erbium_plic.h" +#include "riscv_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: riscv_dispatch_irq + * + * Description: + * Dispatch hart-local traps or claim, dispatch and complete a PLIC + * interrupt. Complete nonzero claims even if their source is unsupported. + * + * Input Parameters: + * vector - Trap cause register value. + * regs - Saved registers for the interrupted task. + * + * Returned Value: + * The register context to restore, possibly belonging to another task. + * + ****************************************************************************/ + +void *riscv_dispatch_irq(uintreg_t vector, uintreg_t *regs) +{ + int irq = vector & RISCV_IRQ_MASK; + uint32_t claim; + + if ((vector & RISCV_IRQ_BIT) != 0) + { + irq += RISCV_IRQ_ASYNC; + } + + if (irq == RISCV_IRQ_EXT) + { + claim = getreg32(ERBIUM_PLIC_CLAIM); + if (claim != 0) + { + if (claim <= ERBIUM_PLIC_NDEV) + { + regs = riscv_doirq(RISCV_IRQ_EXT + claim, regs); + } + + putreg32(claim, ERBIUM_PLIC_CLAIM); + } + } + else + { + regs = riscv_doirq(irq, regs); + } + + return regs; +} diff --git a/arch/risc-v/src/erbium/erbium_memorymap.h b/arch/risc-v/src/erbium/erbium_memorymap.h new file mode 100644 index 00000000000..82f03018014 --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_memorymap.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_ERBIUM_MEMORYMAP_H +#define __ARCH_RISCV_SRC_ERBIUM_ERBIUM_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "riscv_common_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# define ERBIUM_IDLESTACK_BASE (uintptr_t)_ebss +#else +# define ERBIUM_IDLESTACK_BASE _ebss +#endif + +#define ERBIUM_IDLESTACK_SIZE SMP_STACK_SIZE +#define ERBIUM_IDLESTACK_TOP (ERBIUM_IDLESTACK_BASE + ERBIUM_IDLESTACK_SIZE) + +#endif /* __ARCH_RISCV_SRC_ERBIUM_ERBIUM_MEMORYMAP_H */ diff --git a/arch/risc-v/src/erbium/erbium_serial.c b/arch/risc-v/src/erbium/erbium_serial.c new file mode 100644 index 00000000000..11ec3c877ca --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_serial.c @@ -0,0 +1,755 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_serial.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + +#include "chip.h" +#include "hardware/erbium_memorymap.h" +#include "hardware/erbium_sysreg.h" +#include "hardware/erbium_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERBIUM_UART_BAUD_DIV \ + (CONFIG_ERBIUM_UART_CLOCK / (16 * CONFIG_UART0_BAUD)) + +#if CONFIG_UART0_BITS != 8 || CONFIG_UART0_PARITY != 0 || \ + CONFIG_UART0_2STOP != 0 +# error "The Erbium UART driver supports only 8N1" +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct erbium_uart_s +{ + uintptr_t base; + uint8_t irq; + uint32_t ien; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int erbium_setup(struct uart_dev_s *dev); +static void erbium_shutdown(struct uart_dev_s *dev); +static int erbium_attach(struct uart_dev_s *dev); +static void erbium_detach(struct uart_dev_s *dev); +static int erbium_interrupt(int irq, void *context, void *arg); +static int erbium_ioctl(struct file *filep, int cmd, unsigned long arg); +static int erbium_receive(struct uart_dev_s *dev, unsigned int *status); +static void erbium_rxint(struct uart_dev_s *dev, bool enable); +static bool erbium_rxavailable(struct uart_dev_s *dev); +static void erbium_send(struct uart_dev_s *dev, int ch); +static void erbium_txint(struct uart_dev_s *dev, bool enable); +static bool erbium_txready(struct uart_dev_s *dev); +static bool erbium_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; + +static struct erbium_uart_s g_uart0priv = +{ + .base = ERBIUM_UART0_BASE, + .irq = ERBIUM_IRQ_UART0, +}; + +static const struct uart_ops_s g_uart_ops = +{ + .setup = erbium_setup, + .shutdown = erbium_shutdown, + .attach = erbium_attach, + .detach = erbium_detach, + .ioctl = erbium_ioctl, + .receive = erbium_receive, + .rxint = erbium_rxint, + .rxavailable = erbium_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = erbium_send, + .txint = erbium_txint, + .txready = erbium_txready, + .txempty = erbium_txempty, +}; + +static uart_dev_t g_uart0port = +{ +#ifdef CONFIG_UART0_SERIAL_CONSOLE + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: erbium_serialin + * + * Description: + * Read a 32-bit UART register. + * + * Input Parameters: + * priv - UART register base and cached interrupt mask. + * offset - Register offset from the UART base address. + * + * Returned Value: + * The register value. + * + ****************************************************************************/ + +static uint32_t erbium_serialin(struct erbium_uart_s *priv, uintptr_t offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: erbium_serialout + * + * Description: + * Write a 32-bit UART register. + * + * Input Parameters: + * priv - UART register base and cached interrupt mask. + * offset - Register offset from the UART base address. + * value - Value to write. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_serialout(struct erbium_uart_s *priv, uintptr_t offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: erbium_setuartint + * + * Description: + * Update the cached UART interrupt mask and the hardware enable register. + * + * Input Parameters: + * priv - UART register base and cached interrupt mask. + * ien - UART interrupt sources to enable. + * + * Returned Value: + * None. + * + * Assumptions/Limitations: + * The caller must serialize access to the cached interrupt mask. + * + ****************************************************************************/ + +static void erbium_setuartint(struct erbium_uart_s *priv, uint32_t ien) +{ + priv->ien = ien; + erbium_serialout(priv, ERBIUM_UART_IEN_OFFSET, ien); +} + +#ifndef CONFIG_SUPPRESS_UART_CONFIG + +/**************************************************************************** + * Name: erbium_enable_uart + * + * Description: + * Enable the UART peripheral through the system configuration register. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_enable_uart(void) +{ + modifyreg32(ERBIUM_SYSREG_SYSTEM_CONFIG, 0, + ERBIUM_SYSREG_UART_ENABLE); +} +#endif + +/**************************************************************************** + * Name: erbium_disableuartint + * + * Description: + * Disable all UART interrupt sources, optionally saving the old mask. + * + * Input Parameters: + * priv - UART register base and cached interrupt mask. + * ien - Optional location to save the previous interrupt mask. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_disableuartint(struct erbium_uart_s *priv, uint32_t *ien) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + if (ien != NULL) + { + *ien = priv->ien; + } + + erbium_setuartint(priv, 0); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: erbium_restoreuartint + * + * Description: + * Restore a previously saved UART interrupt mask. + * + * Input Parameters: + * priv - UART register base and cached interrupt mask. + * ien - Saved UART interrupt mask. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_restoreuartint(struct erbium_uart_s *priv, uint32_t ien) +{ + irqstate_t flags; + + flags = enter_critical_section(); + erbium_setuartint(priv, ien); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: erbium_putc + * + * Description: + * Wait for space in the transmit FIFO and write one character. + * + * Input Parameters: + * priv - UART register base and cached interrupt mask. + * ch - Character to transmit; only the low eight bits are used. + * + * Returned Value: + * None. + * + * Assumptions/Limitations: + * The caller must serialize access to the transmit FIFO. + * + ****************************************************************************/ + +static void erbium_putc(struct erbium_uart_s *priv, int ch) +{ + while ((erbium_serialin(priv, ERBIUM_UART_STATUS_OFFSET) & + ERBIUM_UART_STATUS_TX_FULL) != 0) + { + } + + erbium_serialout(priv, ERBIUM_UART_TX_OFFSET, (uint32_t)ch & 0xffu); +} + +/**************************************************************************** + * Name: erbium_setup + * + * Description: + * Configure the UART for 8N1 operation and apply its interrupt mask. + * Preserve the existing line configuration when UART setup is suppressed. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * OK. + * + ****************************************************************************/ + +static int erbium_setup(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + +#ifndef CONFIG_SUPPRESS_UART_CONFIG + erbium_enable_uart(); + erbium_serialout(priv, ERBIUM_UART_BAUD_OFFSET, ERBIUM_UART_BAUD_DIV); + erbium_serialout(priv, ERBIUM_UART_CONTROL_OFFSET, + ERBIUM_UART_CONTROL_8N1); + erbium_serialout(priv, ERBIUM_UART_RX_THRESHOLD_OFFSET, 0); +#endif + erbium_setuartint(priv, priv->ien); + + return OK; +} + +/**************************************************************************** + * Name: erbium_shutdown + * + * Description: + * Disable UART interrupts when the serial device is closed. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_shutdown(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + erbium_disableuartint(priv, NULL); +} + +/**************************************************************************** + * Name: erbium_attach + * + * Description: + * Attach the UART interrupt handler and enable its PLIC source. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * OK on success; a negated errno value from irq_attach() on failure. + * + ****************************************************************************/ + +static int erbium_attach(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + int ret; + + ret = irq_attach(priv->irq, erbium_interrupt, dev); + + if (ret == OK) + { + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: erbium_detach + * + * Description: + * Disable the UART PLIC source and detach its interrupt handler. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_detach(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: erbium_interrupt + * + * Description: + * Service enabled receive and transmit events through the serial upper + * half. Limit the number of passes so a persistent event cannot trap the + * CPU in this handler indefinitely. + * + * Input Parameters: + * irq - NuttX interrupt number. + * context - Saved interrupt context. + * arg - Serial device supplied when the handler was attached. + * + * Returned Value: + * OK. + * + ****************************************************************************/ + +static int erbium_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct erbium_uart_s *priv; + uint32_t pending; + int passes; + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + priv = (struct erbium_uart_s *)dev->priv; + + for (passes = 0; passes < 256; passes++) + { + pending = erbium_serialin(priv, ERBIUM_UART_STATUS_OFFSET) & priv->ien; + + if (pending == 0) + { + break; + } + + if ((pending & ERBIUM_UART_IEN_RX_NOT_EMPTY) != 0) + { + uart_recvchars(dev); + } + + if ((pending & ERBIUM_UART_IEN_TX_EMPTY) != 0) + { + uart_xmitchars(dev); + } + } + + return OK; +} + +/**************************************************************************** + * Name: erbium_ioctl + * + * Description: + * Reject unsupported device-specific control requests. + * + * Input Parameters: + * filep - Open serial device file. + * cmd - Requested control operation. + * arg - Operation-specific argument. + * + * Returned Value: + * -ENOTTY; this driver implements no device-specific ioctl commands. + * + ****************************************************************************/ + +static int erbium_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: erbium_receive + * + * Description: + * Read one character from the receive FIFO and optionally report status. + * + * Input Parameters: + * dev - Serial lower-half device. + * status - Optional location to save the UART status register. + * + * Returned Value: + * The received byte, in the range 0 through 255. + * + * Assumptions/Limitations: + * The serial upper half has established that receive data is available. + * + ****************************************************************************/ + +static int erbium_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + if (status != NULL) + { + *status = erbium_serialin(priv, ERBIUM_UART_STATUS_OFFSET); + } + + return (int)(erbium_serialin(priv, ERBIUM_UART_RX_OFFSET) & 0xffu); +} + +/**************************************************************************** + * Name: erbium_rxint + * + * Description: + * Enable or disable receive interrupts. Honor suppression of serial + * interrupts during bring-up. + * + * Input Parameters: + * dev - Serial lower-half device. + * enable - True to enable reception interrupts; false to disable them. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_rxint(struct uart_dev_s *dev, bool enable) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + erbium_setuartint(priv, priv->ien | ERBIUM_UART_IEN_RX_NOT_EMPTY); +#endif + } + else + { + erbium_setuartint(priv, priv->ien & ~ERBIUM_UART_IEN_RX_NOT_EMPTY); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: erbium_rxavailable + * + * Description: + * Check whether the UART receive FIFO contains data. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * True if at least one character is available; otherwise false. + * + ****************************************************************************/ + +static bool erbium_rxavailable(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + return (erbium_serialin(priv, ERBIUM_UART_STATUS_OFFSET) & + ERBIUM_UART_STATUS_RX_NOT_EMPTY) != 0; +} + +/**************************************************************************** + * Name: erbium_send + * + * Description: + * Transmit one character from the serial upper half. + * + * Input Parameters: + * dev - Serial lower-half device. + * ch - Character to transmit. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_send(struct uart_dev_s *dev, int ch) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + erbium_putc(priv, ch); +} + +/**************************************************************************** + * Name: erbium_txint + * + * Description: + * Enable or disable transmit interrupts. Prime the transmit FIFO when + * enabling interrupts, unless serial interrupts are suppressed. + * + * Input Parameters: + * dev - Serial lower-half device. + * enable - True to enable transmission interrupts; false to disable. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void erbium_txint(struct uart_dev_s *dev, bool enable) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + erbium_setuartint(priv, priv->ien | ERBIUM_UART_IEN_TX_EMPTY); + uart_xmitchars(dev); +#endif + } + else + { + erbium_setuartint(priv, priv->ien & ~ERBIUM_UART_IEN_TX_EMPTY); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: erbium_txready + * + * Description: + * Check whether the transmit FIFO has room for another character. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * True if the transmit FIFO is not full; otherwise false. + * + ****************************************************************************/ + +static bool erbium_txready(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + return (erbium_serialin(priv, ERBIUM_UART_STATUS_OFFSET) & + ERBIUM_UART_STATUS_TX_FULL) == 0; +} + +/**************************************************************************** + * Name: erbium_txempty + * + * Description: + * Check whether the UART transmit FIFO is empty. + * + * Input Parameters: + * dev - Serial lower-half device. + * + * Returned Value: + * True if the transmit FIFO is empty; otherwise false. + * + ****************************************************************************/ + +static bool erbium_txempty(struct uart_dev_s *dev) +{ + struct erbium_uart_s *priv = (struct erbium_uart_s *)dev->priv; + + return (erbium_serialin(priv, ERBIUM_UART_STATUS_OFFSET) & + ERBIUM_UART_STATUS_TX_EMPTY) != 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: riscv_earlyserialinit + * + * Description: + * Prepare UART0 for early console output with UART interrupts disabled. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void riscv_earlyserialinit(void) +{ + erbium_disableuartint(&g_uart0priv, NULL); + erbium_setup(&g_uart0port); +} + +/**************************************************************************** + * Name: riscv_serialinit + * + * Description: + * Register UART0 as ttyS0 and, when selected, as the system console. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void riscv_serialinit(void) +{ +#ifdef CONFIG_UART0_SERIAL_CONSOLE + uart_register("/dev/console", &g_uart0port); +#endif + + uart_register("/dev/ttyS0", &g_uart0port); +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Write one low-level console character while preserving the UART + * interrupt mask and the caller's interrupt state. + * + * Input Parameters: + * ch - Character to transmit. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_putc(int ch) +{ + irqstate_t flags; + uint32_t ien; + + flags = enter_critical_section(); + erbium_disableuartint(&g_uart0priv, &ien); + erbium_putc(&g_uart0priv, ch); + erbium_restoreuartint(&g_uart0priv, ien); + leave_critical_section(flags); +} diff --git a/arch/risc-v/src/erbium/erbium_start.c b/arch/risc-v/src/erbium/erbium_start.c new file mode 100644 index 00000000000..c5aac2e734c --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_start.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_start.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "riscv_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: erbium_start + * + * Description: + * Start NuttX on hart 0. The emulator loads initialized data from the ELF + * directly into MRAM, so no ROM-to-RAM data copy is necessary. + * + * Input Parameters: + * None. + * + * Returned Value: + * Does not return. + * + * Assumptions/Limitations: + * Assembly startup has initialized the stack, global pointer and trap + * vector, with interrupts disabled. + * + ****************************************************************************/ + +void erbium_start(void) +{ + uint32_t *dest; + + for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; ) + { + *dest++ = 0; + } + +#ifdef CONFIG_ARCH_FPU + /* Erbium traps FENCE.I to microcode. The ELF loader has already installed + * the image, so initialize the FPU without the common FENCE.I sequence. + */ + + SET_CSR(CSR_STATUS, MSTATUS_FS_INIT); + WRITE_CSR(CSR_FCSR, 0); +#endif + +#ifdef USE_EARLYSERIALINIT + riscv_earlyserialinit(); +#endif + + nx_start(); +} diff --git a/arch/risc-v/src/erbium/erbium_timerisr.c b/arch/risc-v/src/erbium/erbium_timerisr.c new file mode 100644 index 00000000000..8463298cc9f --- /dev/null +++ b/arch/risc-v/src/erbium/erbium_timerisr.c @@ -0,0 +1,68 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/erbium_timerisr.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "hardware/erbium_mtimer.h" +#include "riscv_internal.h" +#include "riscv_mtimer.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_timer_initialize + * + * Description: + * Register the common RISC-V machine timer as the system alarm source. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + struct oneshot_lowerhalf_s *lower; + + lower = riscv_mtimer_initialize(ERBIUM_MTIMER_MTIME, + ERBIUM_MTIMER_MTIMECMP, + RISCV_IRQ_MTIMER, + ERBIUM_MTIMER_FREQ); + + DEBUGASSERT(lower); + + up_alarm_set_lowerhalf(lower); +} diff --git a/arch/risc-v/src/erbium/hardware/erbium_memorymap.h b/arch/risc-v/src/erbium/hardware/erbium_memorymap.h new file mode 100644 index 00000000000..a1edcd3d038 --- /dev/null +++ b/arch/risc-v/src/erbium/hardware/erbium_memorymap.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/hardware/erbium_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_HARDWARE_ERBIUM_MEMORYMAP_H +#define __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_MEMORYMAP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERBIUM_SYSREG_BASE 0x02000000ul +#define ERBIUM_UART0_BASE 0x02004000ul +#define ERBIUM_MTIMECMP_BASE 0x80f40208ul +#define ERBIUM_MTIME_BASE 0x80f40200ul +#define ERBIUM_PLIC_BASE 0xa0000000ul + +#endif /* __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_MEMORYMAP_H */ diff --git a/arch/risc-v/src/erbium/hardware/erbium_mtimer.h b/arch/risc-v/src/erbium/hardware/erbium_mtimer.h new file mode 100644 index 00000000000..0f4ba84fb12 --- /dev/null +++ b/arch/risc-v/src/erbium/hardware/erbium_mtimer.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/hardware/erbium_mtimer.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_HARDWARE_ERBIUM_MTIMER_H +#define __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_MTIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/erbium_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERBIUM_MTIMER_FREQ CONFIG_ERBIUM_MTIMER_FREQ +#define ERBIUM_MTIMER_MTIME ERBIUM_MTIME_BASE +#define ERBIUM_MTIMER_MTIMECMP ERBIUM_MTIMECMP_BASE + +#endif /* __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_MTIMER_H */ diff --git a/arch/risc-v/src/erbium/hardware/erbium_plic.h b/arch/risc-v/src/erbium/hardware/erbium_plic.h new file mode 100644 index 00000000000..8c4d3e7ce61 --- /dev/null +++ b/arch/risc-v/src/erbium/hardware/erbium_plic.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/hardware/erbium_plic.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_HARDWARE_ERBIUM_PLIC_H +#define __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_PLIC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/erbium_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERBIUM_PLIC_NSOURCE 7 +#define ERBIUM_PLIC_NDEV (ERBIUM_PLIC_NSOURCE - 1) + +#define ERBIUM_PLIC_PRIORITY (ERBIUM_PLIC_BASE + 0x000000) +#define ERBIUM_PLIC_PENDING (ERBIUM_PLIC_BASE + 0x001000) +#define ERBIUM_PLIC_ENABLE1 (ERBIUM_PLIC_BASE + 0x002000) +#define ERBIUM_PLIC_THRESHOLD (ERBIUM_PLIC_BASE + 0x200000) +#define ERBIUM_PLIC_CLAIM (ERBIUM_PLIC_BASE + 0x200004) + +#endif /* __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_PLIC_H */ diff --git a/arch/risc-v/src/erbium/hardware/erbium_sysreg.h b/arch/risc-v/src/erbium/hardware/erbium_sysreg.h new file mode 100644 index 00000000000..0f35ff22d20 --- /dev/null +++ b/arch/risc-v/src/erbium/hardware/erbium_sysreg.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/hardware/erbium_sysreg.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_HARDWARE_ERBIUM_SYSREG_H +#define __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_SYSREG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/erbium_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERBIUM_SYSREG_SYSTEM_CONFIG (ERBIUM_SYSREG_BASE + 0x08) +#define ERBIUM_SYSREG_UART_ENABLE (1u << 6) + +#endif /* __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_SYSREG_H */ diff --git a/arch/risc-v/src/erbium/hardware/erbium_uart.h b/arch/risc-v/src/erbium/hardware/erbium_uart.h new file mode 100644 index 00000000000..031d2e5562a --- /dev/null +++ b/arch/risc-v/src/erbium/hardware/erbium_uart.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * arch/risc-v/src/erbium/hardware/erbium_uart.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_HARDWARE_ERBIUM_UART_H +#define __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_UART_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Shakti UART registers on the Erbium peripheral bus. */ + +#define ERBIUM_UART_BAUD_OFFSET 0x00 +#define ERBIUM_UART_TX_OFFSET 0x08 +#define ERBIUM_UART_RX_OFFSET 0x10 +#define ERBIUM_UART_STATUS_OFFSET 0x18 +#define ERBIUM_UART_CONTROL_OFFSET 0x28 +#define ERBIUM_UART_IEN_OFFSET 0x30 +#define ERBIUM_UART_RX_THRESHOLD_OFFSET 0x40 + +#define ERBIUM_UART_STATUS_TX_EMPTY (1u << 0) +#define ERBIUM_UART_STATUS_TX_FULL (1u << 1) +#define ERBIUM_UART_STATUS_RX_NOT_EMPTY (1u << 2) + +#define ERBIUM_UART_IEN_TX_EMPTY (1u << 0) +#define ERBIUM_UART_IEN_RX_NOT_EMPTY (1u << 2) +#define ERBIUM_UART_CONTROL_8N1 (8u << 5) + +#endif /* __ARCH_RISCV_SRC_ERBIUM_HARDWARE_ERBIUM_UART_H */ diff --git a/boards/Kconfig b/boards/Kconfig index bbbfa45b553..388f19bbd1a 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1239,6 +1239,13 @@ config ARCH_BOARD_MAIX_BIT This is the board configuration for the port of NuttX to the Sipeed Maix Bit board. This board features the RISC-V K210 +config ARCH_BOARD_ERBIUM_MINION + bool "AIFoundry Erbium Minion" + depends on ARCH_CHIP_ERBIUM + ---help--- + This is the board configuration for the AIFoundry Erbium simulator + minion target. This board features an RV64IMFC Erbium hart. + config ARCH_BOARD_SMARTL_C906 bool "smartl evaluation board for C906" depends on ARCH_CHIP_C906 @@ -4032,6 +4039,7 @@ config ARCH_BOARD default "lpcxpresso-lpc54628" if ARCH_BOARD_LPCXPRESSO_LPC54628 default "lx_cpu" if ARCH_BOARD_LX_CPU default "maix-bit" if ARCH_BOARD_MAIX_BIT + default "minion" if ARCH_BOARD_ERBIUM_MINION default "smartl-c906" if ARCH_BOARD_SMARTL_C906 default "icicle" if ARCH_BOARD_ICICLE_MPFS default "m100pfsevp" if ARCH_BOARD_M100PFSEVP_MPFS @@ -5281,6 +5289,9 @@ endif if ARCH_BOARD_MAIX_BIT source "boards/risc-v/k210/maix-bit/Kconfig" endif +if ARCH_BOARD_ERBIUM_MINION +source "boards/risc-v/erbium/minion/Kconfig" +endif if ARCH_BOARD_SMARTL_C906 source "boards/risc-v/c906/smartl-c906/Kconfig" endif diff --git a/boards/risc-v/erbium/minion/CMakeLists.txt b/boards/risc-v/erbium/minion/CMakeLists.txt new file mode 100644 index 00000000000..027258fda2b --- /dev/null +++ b/boards/risc-v/erbium/minion/CMakeLists.txt @@ -0,0 +1,23 @@ +# ############################################################################## +# boards/risc-v/erbium/minion/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +add_subdirectory(src) diff --git a/boards/risc-v/erbium/minion/Kconfig b/boards/risc-v/erbium/minion/Kconfig new file mode 100644 index 00000000000..809c30996ca --- /dev/null +++ b/boards/risc-v/erbium/minion/Kconfig @@ -0,0 +1,10 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_ERBIUM_MINION + +endif diff --git a/boards/risc-v/erbium/minion/cmake/Toolchain.cmake b/boards/risc-v/erbium/minion/cmake/Toolchain.cmake new file mode 100644 index 00000000000..1b1b845af12 --- /dev/null +++ b/boards/risc-v/erbium/minion/cmake/Toolchain.cmake @@ -0,0 +1,28 @@ +# ############################################################################## +# boards/risc-v/erbium/minion/cmake/Toolchain.cmake +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +# Erbium executes floating-point divide and square root in microcode, which this +# image does not provide. Use software helpers for those operations. + +if(CONFIG_ARCH_FPU) + add_compile_options(-mno-fdiv) +endif() diff --git a/boards/risc-v/erbium/minion/configs/nsh/defconfig b/boards/risc-v/erbium/minion/configs/nsh/defconfig new file mode 100644 index 00000000000..3f09839a999 --- /dev/null +++ b/boards/risc-v/erbium/minion/configs/nsh/defconfig @@ -0,0 +1,48 @@ +# +# 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_ARCH="risc-v" +CONFIG_ARCH_BOARD="minion" +CONFIG_ARCH_BOARD_ERBIUM_MINION=y +CONFIG_ARCH_CHIP="erbium" +CONFIG_ARCH_CHIP_ERBIUM=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=400000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIBM=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RAM_SIZE=16776704 +CONFIG_RAM_START=0x40000200 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_YEAR=2026 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=4096 +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/risc-v/erbium/minion/configs/ostest/defconfig b/boards/risc-v/erbium/minion/configs/ostest/defconfig new file mode 100644 index 00000000000..413834d1be1 --- /dev/null +++ b/boards/risc-v/erbium/minion/configs/ostest/defconfig @@ -0,0 +1,45 @@ +# +# 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_ARCH="risc-v" +CONFIG_ARCH_BOARD="minion" +CONFIG_ARCH_BOARD_ERBIUM_MINION=y +CONFIG_ARCH_CHIP="erbium" +CONFIG_ARCH_CHIP_ERBIUM=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL=y +CONFIG_BOARDCTL_MKRD=y +CONFIG_BOARD_LOOPSPERMSEC=400000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="ostest_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIBM=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RAM_SIZE=16776704 +CONFIG_RAM_START=0x40000200 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_YEAR=2026 +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/risc-v/erbium/minion/include/board.h b/boards/risc-v/erbium/minion/include/board.h new file mode 100644 index 00000000000..865933cc108 --- /dev/null +++ b/boards/risc-v/erbium/minion/include/board.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * boards/risc-v/erbium/minion/include/board.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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_ERBIUM_MINION_INCLUDE_BOARD_H +#define __BOARDS_RISCV_ERBIUM_MINION_INCLUDE_BOARD_H + +#define LED_STARTED 0 +#define LED_HEAPALLOCATE 1 +#define LED_IRQSENABLED 2 +#define LED_STACKCREATED 3 +#define LED_INIRQ 4 +#define LED_SIGNAL 5 +#define LED_ASSERTION 6 +#define LED_PANIC 7 + +#endif /* __BOARDS_RISCV_ERBIUM_MINION_INCLUDE_BOARD_H */ diff --git a/boards/risc-v/erbium/minion/scripts/Make.defs b/boards/risc-v/erbium/minion/scripts/Make.defs new file mode 100644 index 00000000000..c4d0b779062 --- /dev/null +++ b/boards/risc-v/erbium/minion/scripts/Make.defs @@ -0,0 +1,47 @@ +############################################################################ +# boards/risc-v/erbium/minion/scripts/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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/common/Toolchain.defs + +# Erbium executes floating-point divide and square root in microcode, which +# this image does not provide. Use software helpers for those operations. + +ifeq ($(CONFIG_ARCH_FPU),y) + ARCHCPUFLAGS += -mno-fdiv +endif + +LDSCRIPT = ld.script +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS += $(CFLAGS) -D__ASSEMBLY__ + +CELFFLAGS = $(CFLAGS) +CXXELFFLAGS = $(CXXFLAGS) +LDELFFLAGS = --oformat elf64-littleriscv -r -e main +LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) diff --git a/boards/risc-v/erbium/minion/scripts/ld.script b/boards/risc-v/erbium/minion/scripts/ld.script new file mode 100644 index 00000000000..907f788527a --- /dev/null +++ b/boards/risc-v/erbium/minion/scripts/ld.script @@ -0,0 +1,126 @@ +/**************************************************************************** + * boards/risc-v/erbium/minion/scripts/ld.script + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + +EXTERN(__start) +ENTRY(__start) + +PHDRS +{ + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); +} + +SECTIONS +{ + /* The Erbium simulator reserves the first 512 bytes of MRAM. */ + . = CONFIG_RAM_START; + + .rom_start : { + _stext = .; + KEEP(*(.text.__start)) + } :text + + . = ALIGN(4); + + .exceptions : { + KEEP(*(.text.exceptions)) + } :text + + .text : { + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.gnu.linkonce.t.*) + *(.init) + *(.fini) + _etext = .; + } :text + + .rodata : { + _srodata = .; + *(.rodata) + *(.rodata.*) + *(.srodata .srodata.*) + *(.gnu.linkonce.r*) + _erodata = .; + } :text + + .tdata : { + _stdata = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*); + _etdata = ABSOLUTE(.); + } :data + + .tbss : { + _stbss = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon); + _etbss = ABSOLUTE(.); + } :data + + _eronly = ABSOLUTE(.); + + .data : { + _sdata = .; + PROVIDE(__global_pointer$ = . + 0x800); + *(.data) + *(.data.*) + *(.sdata .sdata.*) + *(.gnu.linkonce.d*) + . = ALIGN(8); + _edata = .; + } :data + + .init_array : { + . = ALIGN(8); + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array .ctors)) + _einit = ABSOLUTE(.); + } :data + + .bss (NOLOAD) : { + . = ALIGN(8); + _sbss = .; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(16); + _ebss = .; + } :data + + ASSERT(_ebss + ALIGN(CONFIG_IDLETHREAD_STACKSIZE, 16) < CONFIG_RAM_END, + "Erbium image and idle stack exceed MRAM") + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/risc-v/erbium/minion/src/CMakeLists.txt b/boards/risc-v/erbium/minion/src/CMakeLists.txt new file mode 100644 index 00000000000..fe82c479a1d --- /dev/null +++ b/boards/risc-v/erbium/minion/src/CMakeLists.txt @@ -0,0 +1,27 @@ +# ############################################################################## +# boards/risc-v/erbium/minion/src/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +set(SRCS erbium_bringup.c) + +target_sources(board PRIVATE ${SRCS}) + +set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/ld.script") diff --git a/boards/risc-v/erbium/minion/src/Makefile b/boards/risc-v/erbium/minion/src/Makefile new file mode 100644 index 00000000000..c2273b40d94 --- /dev/null +++ b/boards/risc-v/erbium/minion/src/Makefile @@ -0,0 +1,27 @@ +############################################################################ +# boards/risc-v/erbium/minion/src/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 + +CSRCS = erbium_bringup.c + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/risc-v/erbium/minion/src/erbium_bringup.c b/boards/risc-v/erbium/minion/src/erbium_bringup.c new file mode 100644 index 00000000000..8862fdc6a7c --- /dev/null +++ b/boards/risc-v/erbium/minion/src/erbium_bringup.c @@ -0,0 +1,67 @@ +/**************************************************************************** + * boards/risc-v/erbium/minion/src/erbium_bringup.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * Mount board filesystems after OS initialization and before the initial + * application starts. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ +#ifdef CONFIG_FS_PROCFS + int ret; + + ret = nx_mount(NULL, "/proc", "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: procfs mount failed: %d\n", ret); + } +#endif +} +#endif diff --git a/boards/risc-v/erbium/minion/tools/test_emu.py b/boards/risc-v/erbium/minion/tools/test_emu.py new file mode 100644 index 00000000000..3befaf42c1c --- /dev/null +++ b/boards/risc-v/erbium/minion/tools/test_emu.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# boards/risc-v/erbium/minion/tools/test_emu.py +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. + +"""Exercise prebuilt Erbium NuttX images and record reproducible results.""" + +import argparse +import hashlib +import json +import re +import subprocess +import time +from pathlib import Path + +FAILURE = re.compile( + r"\bERROR\b|Assertion failed|ASSERTION|PANIC|riscv_exception:|Unhandled exception" + r"|nsh: .*?(?:failed|not found|invalid)" + r"|ostest_main: Exiting with status -?[1-9]", + re.I, +) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--emu", type=Path, required=True) + parser.add_argument("--elf", type=Path, required=True) + parser.add_argument("--mode", choices=["nsh", "ostest"], required=True) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--timeout", type=int, default=14400) + parser.add_argument("--max-cycles", default="100000000000") + parser.add_argument("--extra-harts", action="store_true") + args = parser.parse_args() + if args.timeout <= 0: + parser.error("--timeout must be positive") + for path in (args.emu, args.elf): + if not path.is_file(): + parser.error(f"Input file does not exist: {path}") + args.output.mkdir(parents=True, exist_ok=True) + uart = args.output / "uart.log" + emulator = args.output / "emulator.log" + uart.write_bytes(b"") + command = [ + str(args.emu.resolve()), + "-elf_load", + str(args.elf.resolve()), + "-reset_pc", + "0x40000200", + "-max_cycles", + args.max_cycles, + "-uart_tx_file", + str(uart.resolve()), + "-mem_reset", + "165", + ] + if args.extra_harts: + command += ["-minions", "3"] + else: + command += ["-single_thread"] + start = time.monotonic() + deadline = start + args.timeout + proc = None + checks = [] + failure = None + try: + with emulator.open("wb") as log: + proc = subprocess.Popen( + command, stdin=subprocess.PIPE, stdout=log, stderr=log + ) + + def wait_for(needle, offset=0): + while True: + output = uart.read_text(errors="replace") if uart.exists() else "" + if FAILURE.search(output): + raise RuntimeError("Guest reported a failure; inspect uart.log") + if needle in output[offset:]: + return output + if proc.poll() is not None: + raise RuntimeError( + f"Emulator exited with {proc.returncode} before {needle!r}" + ) + if time.monotonic() >= deadline: + raise TimeoutError(f"Timed out waiting for {needle!r}") + time.sleep(0.1) + + if args.mode == "ostest": + text = wait_for("ostest_main: Exiting with status 0") + if "Final memory usage:" not in text: + raise RuntimeError("Missing final memory report") + for marker in [ + "user_main: Exiting", + "FPU#1: Succeeded", + "FPU#2: Succeeded", + "user_main: semaphore test", + "user_main: signal handler test", + "user_main: pthread_exit() test", + "wqueue_test: teardown done", + ]: + if marker.lower() not in text.lower(): + raise RuntimeError( + f"Missing expected ostest coverage: {marker}" + ) + checks.append("Complete ostest, including FPU context switching") + else: + text = wait_for("nsh> ") + checks.append("NSH boot") + + def run_command(command_text, expected=None): + nonlocal text + offset = len(text) + # The emulator drains host input into a finite RX FIFO. + # Wait for each echoed character to avoid overrunning it. + for i, char in enumerate(command_text): + proc.stdin.write(char.encode()) + proc.stdin.flush() + wait_for(command_text[: i + 1], offset) + proc.stdin.write(b"\n") + proc.stdin.flush() + text = wait_for("nsh> ", offset) + response = text[offset:].split("\n", 1)[-1] + if expected and expected not in response: + raise RuntimeError( + f"Missing {expected!r} in response to {command_text!r}" + ) + checks.append(command_text) + return response + + def uptime(): + response = run_command("cat /proc/uptime") + match = re.search(r"^\s*(\d+\.\d+)\s*$", response, re.M) + if not match: + raise RuntimeError("Missing numeric procfs uptime") + return float(match[1]) + + for command_text, expected in [ + ("uname -a", "risc-v"), + ("help", "uname"), + ("ps", "Idle_Task"), + ]: + run_command(command_text, expected) + + before = uptime() + run_command("sleep 1") + if uptime() - before < 0.99: + raise RuntimeError("Guest uptime did not advance by one second") + checks.append("Timer advances during sleep") + run_command("echo ERBIUM_UART_TIMER_OK", "ERBIUM_UART_TIMER_OK") + run_command("free", "total") + time.sleep(0.5) + run_command("echo ERBIUM_LATE_RX_OK", "ERBIUM_LATE_RX_OK") + checks.append("UART RX after idle") + except (Exception, KeyboardInterrupt) as error: + failure = str(error) or type(error).__name__ + finally: + if proc is not None and proc.poll() is None: + proc.terminate() + try: + proc.wait(timeout=5) + except subprocess.TimeoutExpired: + proc.kill() + proc.wait(timeout=5) + result = { + "passed": failure is None, + "error": failure, + "checks": checks, + "command": command, + "duration_seconds": time.monotonic() - start, + "elf_sha256": hashlib.sha256(args.elf.read_bytes()).hexdigest(), + "emulator_sha256": hashlib.sha256(args.emu.read_bytes()).hexdigest(), + "emulator_returncode": None if proc is None else proc.returncode, + } + if failure is None and re.search( + r": (ERROR|FATAL) ", emulator.read_text(errors="replace") + ): + failure = "Emulator reported an error; inspect emulator.log" + result["passed"] = False + result["error"] = failure + (args.output / "result.json").write_text(json.dumps(result, indent=2) + "\n") + print(json.dumps(result, indent=2), flush=True) + return 1 if failure else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/ci/testlist/risc-v-01.dat b/tools/ci/testlist/risc-v-01.dat index b652e87160d..2ea92fae06b 100644 --- a/tools/ci/testlist/risc-v-01.dat +++ b/tools/ci/testlist/risc-v-01.dat @@ -1,3 +1,7 @@ /risc-v/[a-d]* /risc-v/e[0-r]* -bl602evb:elf + +# Erbium also supports the CMake build. +CMake,minion:nsh +CMake,minion:ostest