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 <afonso.oliveira707@gmail.com>
This commit is contained in:
Afonso Oliveira 2026-09-21 20:57:59 +01:00 • committed by Xiang Xiao
parent 95cdd306f0
commit 0b35d45b2c
33 changed files with 2398 additions and 0 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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})

View file

@ -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.

View file

@ -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

View file

@ -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 <nuttx/config.h>
#include <arch/chip/chip.h>
#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 */

View file

@ -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 <nuttx/config.h>
#include <arch/arch.h>
#include <arch/irq.h>
#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

View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <nuttx/irq.h>
#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);
}

View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <nuttx/irq.h>
#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;
}

View file

@ -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 */

View file

@ -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 <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/serial/serial.h>
#include <arch/irq.h>
#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);
}

View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <nuttx/init.h>
#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();
}

View file

@ -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 <nuttx/config.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/timers/arch_alarm.h>
#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);
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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)

View file

@ -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 <nuttx/config.h>
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) }
}

View file

@ -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")

View file

@ -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

View file

@ -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 <nuttx/config.h>
#include <sys/mount.h>
#include <syslog.h>
#include <nuttx/board.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* 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

View file

@ -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())

View file

@ -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