Repository: apache/nuttx
Pull request #15921: arch/risc-v/eic7700x: Add support for ESWIN EIC7700X SoC
Author: login: lupyuen
Labels: name: Area: Documentation
description: Improvements or additions to documentation
name: Arch: risc-v
description: Issues related to the RISC-V (32-bit or 64-bit) architecture
name: Size: XL
description: The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces.
Created: 2025-03-02T02:02:04Z | Merged: 2025-03-04T14:27:48Z

## Summary

This PR adds support for the ESWIN EIC7700X RISC-V SoC. This will be used by the upcoming port of NuttX for PINE64 StarPro64 SBC.

Most of the code was derived from NuttX for SOPHGO SG2000 SoC. [The modified code is explained here](https://lupyuen.github.io/articles/starpro64#appendix-port-nuttx-to-starpro64)

### Modified Files in arch/risc-v

`Kconfig`: Added ARCH_CHIP_EIC7700X for EIC7700X SoC

### New Files in arch/risc-v

`include/eic7700x/chip.h`: EIC7700X Definitions

`include/eic7700x/irq.h`: External Interrupts

`src/eic7700x/chip.h`: Interrupt Stack Macro

`src/eic7700x/eic7700x_allocateheap.c`: Kernel Heap

`src/eic7700x/eic7700x_head.S`: Linux Header and Boot Code

`src/eic7700x/eic7700x_irq.c`: Configure Interrupts

`src/eic7700x/eic7700x_irq_dispatch.c`: Dispatch Interrupts

`src/eic7700x/eic7700x_memorymap.h`: Memory Map

`src/eic7700x/eic7700x_mm_init.c`, `eic7700x_mm_init.h`: Memory Mgmt

`src/eic7700x/eic7700x_pgalloc.c`: Page Allocator

`src/eic7700x/eic7700x_start.c`: Startup Code

`src/eic7700x/eic7700x_timerisr.c`: Timer Interrupt

`src/eic7700x/hardware/eic7700x_memorymap.h`: PLIC and UART Base Address

`src/eic7700x/hardware/eic7700x_plic.h`: PLIC Register Addresses

`src/eic7700x/Kconfig`: EIC7700X Config

`src/eic7700x/Make.defs`: Makefile

### Documentation

`platforms/risc-v/eic7700x/index.rst`: Added EIC7700X SoC

## Impact

This PR is needed for the upcoming port of NuttX for PINE64 StarPro64 SBC.

No impact on existing code, since the EIC7700X source files are not used by existing code.

## Testing

We tested the EIC7700X source files on PINE64 StarPro64 SBC. NuttX boots correctly to NSH Shell and passes OSTest:

- [Board Source Code for StarPro64](https://github.com/lupyuen2/wip-nuttx/pull/94/files)
- [NuttX Log for StarPro64](https://gist.github.com/lupyuen/9bfa9f0d023b92f5f20a61d07c2c1c15)
- [Build Log for StarPro64](https://gist.github.com/lupyuen/91d74fc9e6641edf69adc56a9386b0ca)

```text
NuttShell (NSH) NuttX-12.8.0
nsh> uname -a
NuttX 12.8.0 f81a1ae9ef Mar  3 2025 06:32:03 risc-v starpro64

nsh> free
      total       used       free    maxused    maxfree  nused  nfree name
    2057216      11632    2045584      33320    2042800     38      6 Kmem
   20971520     720896   20250624              20250624               Page

nsh> ls -l /dev
/dev:
 crw-rw-rw-           0 console
 crw-rw-rw-           0 null
 brw-rw-rw-    16777216 ram0
 crw-rw-rw-           0 ttyS0
 crw-rw-rw-           0 zero

nsh> ps
  PID GROUP PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK            STACK    USED FILLED COMMAND
    0     0   0 FIFO     Kthread   - Ready              0000000000000000 0003056 0001040  34.0%  Idle_Task
    1     0 100 RR       Kthread   - Waiting  Semaphore 0000000000000000 0001968 0000720  36.5%  lpwork 0x80400100 0x80400148
    3     3 100 RR       Task      - Running            0000000000000000 0003008 0001872  62.2%  /system/bin/init

nsh> hello
Hello, World!!

nsh> getprime
Set thread priority to 10
Set thread policy to SCHED_RR
Start thread #0
thread #0 started, looking for primes < 10000, doing 10 run(s)
thread #0 finished, found 1230 primes, last one was 9973
Done
getprime took 134 msec

nsh> ostest
...
Final memory usage:
VARIABLE  BEFORE   AFTER
======== ======== ========
arena       81000    81000
ordblks         2        3
mxordblk    7cff8    78ff8
uordblks     2660     4570
fordblks    7e9a0    7ca90
user_main: Exiting
ostest_main: Exiting with status 0
```



Diff:
diff --git a/Documentation/platforms/risc-v/eic7700x/index.rst b/Documentation/platforms/risc-v/eic7700x/index.rst
new file mode 100644
index 0000000000000..dae8b12755355
--- /dev/null
+++ b/Documentation/platforms/risc-v/eic7700x/index.rst
@@ -0,0 +1,16 @@
+==============
+ESWIN EIC7700X
+==============
+
+`ESWIN EIC7700X <https://www.eswincomputing.com/en/products/index/36.html>`_ is a 64-bit RISC-V SoC with 4 RISC-V Cores:
+
+- **Processors:** 4 x RV64GC 1.4 GHz 64-bit RISC-V Cores
+- **NPU:** 19.95 TOPS INT8
+- **Memory:** Up to 32 GB 64-bit LPDDR4 / 4x / 5
+- **Storage:** eMMC 5.1, 2 x SDIO 3.0, SATA3, SPI NOR Flash
+- **Video Decoding:** H.265 up to 8K @ 50 FPS, or 32 x 1080P @ 30 FPS
+- **Video Encoding:** H.265 up to 8K @ 25 FPS, or 13 x 1080P @ 30 FPS
+- **Image Processing:** JPEG ISO/IEC 10918-1, ITU-T T.81
+- **Network:** 2 x GMAC, RGMII supported
+- **PCI Express:** 4-lane PCIe 3.0 (RC + EP)
+- **Peripherals:** 2 x USB 3.0 DRD (Host + Device), 12 x I2C, 5 x UART, 2 x SPI, 3 x I2S (Slave + Master)
diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 2cd078f8d82df..7179efe3cf134 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -350,6 +350,25 @@ config ARCH_CHIP_SG2000
 	---help---
 		SOPHGO SG2000 SoC.
 
+config ARCH_CHIP_EIC7700X
+	bool "ESWIN EIC7700X"
+	select ARCH_RV64
+	select ARCH_RV_ISA_M
+	select ARCH_RV_ISA_A
+	select ARCH_RV_ISA_C
+	select ARCH_HAVE_FPU
+	select ARCH_HAVE_DPFPU
+	select ARCH_HAVE_MULTICPU
+	select ARCH_HAVE_MPU
+	select ARCH_MMU_TYPE_SV39
+	select ARCH_HAVE_ADDRENV
+	select ARCH_NEED_ADDRENV_MAPPING
+	select ARCH_HAVE_S_MODE
+	select ONESHOT
+	select ALARM_ARCH
+	---help---
+		ESWIN EIC7700X SoC.
+
 config ARCH_CHIP_RISCV_CUSTOM
 	bool "Custom RISC-V chip"
 	select ARCH_CHIP_CUSTOM
@@ -534,6 +553,7 @@ config ARCH_CHIP
 	default "bl808"                 if ARCH_CHIP_BL808
 	default "k230"                  if ARCH_CHIP_K230
 	default "sg2000"                if ARCH_CHIP_SG2000
+	default "eic7700x"              if ARCH_CHIP_EIC7700X
 
 config ARCH_RISCV_INTXCPT_EXTENSIONS
 	bool "RISC-V Integer Context Extensions"
@@ -774,4 +794,7 @@ endif
 if ARCH_CHIP_SG2000
 source "arch/risc-v/src/sg2000/Kconfig"
 endif
+if ARCH_CHIP_EIC7700X
+source "arch/risc-v/src/eic7700x/Kconfig"
+endif
 endif # ARCH_RISCV
diff --git a/arch/risc-v/include/eic7700x/chip.h b/arch/risc-v/include/eic7700x/chip.h
new file mode 100644
index 0000000000000..1bfe6a46c0ffc
--- /dev/null
+++ b/arch/risc-v/include/eic7700x/chip.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+ * arch/risc-v/include/eic7700x/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_EIC7700X_CHIP_H
+#define __ARCH_RISCV_INCLUDE_EIC7700X_CHIP_H
+
+#endif /* __ARCH_RISCV_INCLUDE_EIC7700X_CHIP_H */
diff --git a/arch/risc-v/include/eic7700x/irq.h b/arch/risc-v/include/eic7700x/irq.h
new file mode 100644
index 0000000000000..b2b1cec25a9b9
--- /dev/null
+++ b/arch/risc-v/include/eic7700x/irq.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ * arch/risc-v/include/eic7700x/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_EIC7700X_IRQ_H
+#define __ARCH_RISCV_INCLUDE_EIC7700X_IRQ_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Number of PLIC External Interrupts supported */
+
+#define EIC7700X_PLIC_IRQS 458
+
+/* Map RISC-V exception code to NuttX IRQ */
+
+#define NR_IRQS (RISCV_IRQ_SEXT + EIC7700X_PLIC_IRQS)
+
+#endif /* __ARCH_RISCV_INCLUDE_EIC7700X_IRQ_H */
diff --git a/arch/risc-v/src/eic7700x/Kconfig b/arch/risc-v/src/eic7700x/Kconfig
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/arch/risc-v/src/eic7700x/Make.defs b/arch/risc-v/src/eic7700x/Make.defs
new file mode 100644
index 0000000000000..0180847c90e16
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/Make.defs
@@ -0,0 +1,32 @@
+############################################################################
+# arch/risc-v/src/eic7700x/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
+
+# Specify our HEAD assembly file.  This will be linked as
+# the first object file, so it will appear at address 0
+HEAD_ASRC = eic7700x_head.S
+
+# Specify our C code within this directory to be included
+CHIP_CSRCS  = eic7700x_start.c eic7700x_irq_dispatch.c eic7700x_irq.c
+CHIP_CSRCS += eic7700x_timerisr.c eic7700x_allocateheap.c
+CHIP_CSRCS += eic7700x_mm_init.c eic7700x_pgalloc.c
diff --git a/arch/risc-v/src/eic7700x/chip.h b/arch/risc-v/src/eic7700x/chip.h
new file mode 100644
index 0000000000000..974a2b68b52e4
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/chip.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/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_EIC7700X_CHIP_H
+#define __ARCH_RISCV_SRC_EIC7700X_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/* Include the chip capabilities file */
+
+#include <arch/eic7700x/chip.h>
+
+#include "eic7700x_memorymap.h"
+
+#include "hardware/eic7700x_memorymap.h"
+#include "hardware/eic7700x_plic.h"
+
+#include "riscv_internal.h"
+#include "riscv_percpu.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Hart ID that booted NuttX (0 to 3) */
+
+#ifndef __ASSEMBLY__
+extern int g_eic7700x_boot_hart;
+#endif
+
+/****************************************************************************
+ * Macro Definitions
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+
+/****************************************************************************
+ * Name: setintstack
+ *
+ * Description:
+ *   Set the current stack pointer to the "top" of the correct interrupt
+ *   stack for the current CPU.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
+.macro  setintstack tmp0, tmp1
+  up_cpu_index \tmp0
+  li    \tmp1, STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK)
+  mul   \tmp1, \tmp0, \tmp1
+  la    \tmp0, g_intstacktop
+  sub   sp, \tmp0, \tmp1
+.endm
+#endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 15 */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 15
+#if !defined(CONFIG_SMP) && defined(CONFIG_ARCH_USE_S_MODE)
+.macro  setintstack tmp0, tmp1
+  csrr    \tmp0, CSR_SCRATCH
+  REGLOAD sp, RISCV_PERCPU_IRQSTACK(\tmp0)
+.endm
+#endif /* !defined(CONFIG_SMP) && defined(CONFIG_ARCH_USE_S_MODE) */
+#endif /* CONFIG_ARCH_INTERRUPTSTACK > 15 */
+
+#endif /* __ASSEMBLY__  */
+#endif /* __ARCH_RISCV_SRC_EIC7700X_CHIP_H */
diff --git a/arch/risc-v/src/eic7700x/eic7700x_allocateheap.c b/arch/risc-v/src/eic7700x/eic7700x_allocateheap.c
new file mode 100644
index 0000000000000..37b2a3262935c
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_allocateheap.c
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_allocateheap.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 <nuttx/kmalloc.h>
+#include <nuttx/userspace.h>
+#include <nuttx/arch.h>
+#include <arch/board/board_memorymap.h>
+#include "riscv_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define KRAM_END    KSRAM_END
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, user-space heap.
+ *
+ *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   allocated (and protected) by an analogous up_allocate_kheap().
+ *
+ *   The following memory map is assumed for the flat build:
+ *
+ *   .data region.  Size determined at link time.
+ *   .bss  region  Size determined at link time.
+ *   IDLE thread stack.  Size determined by CONFIG_IDLETHREAD_STACKSIZE.
+ *   Heap.  Extends to the end of User SRAM.
+ *
+ *   The following memory map is assumed for the protected build.
+ *   The kernel and user space have their own dedicated heap spaces.
+ *
+ *   User .data region         Size determined at link time
+ *   User .bss region          Size determined at link time
+ *   User heap                 Extends to the end of User SRAM
+ *   Kernel .data region       Size determined at link time
+ *   Kernel .bss  region       Size determined at link time
+ *   Kernel IDLE thread stack  Size determined by CONFIG_IDLETHREAD_STACKSIZE
+ *   Kernel heap               Size determined by CONFIG_MM_KERNEL_HEAPSIZE
+ *
+ ****************************************************************************/
+
+void up_allocate_kheap(void **heap_start, size_t *heap_size)
+{
+  /* Return the heap settings */
+
+  *heap_start = (void *)g_idle_topstack;
+  *heap_size = KRAM_END - g_idle_topstack;
+}
diff --git a/arch/risc-v/src/eic7700x/eic7700x_head.S b/arch/risc-v/src/eic7700x/eic7700x_head.S
new file mode 100644
index 0000000000000..24a659fefb6c3
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_head.S
@@ -0,0 +1,108 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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_internal.h"
+#include "riscv_macros.S"
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+  /* Exported Symbols */
+
+  .section .text
+  .global __start
+
+__start:
+
+  /* DO NOT MODIFY. Image Header expected by Linux bootloaders.
+   *
+   * This `li` instruction has no meaningful effect except that
+   * its opcode forms the magic "MZ" signature of a PE/COFF file
+   * that is required for UEFI applications.
+   *
+   * Some bootloaders check the magic "MZ" to see if the image is a valid
+   * Linux image. But modifying the bootLoader is unnecessary unless we
+   * need to do a customized secure boot. So we just put "MZ" in the
+   * header to make the bootloader happy.
+   */
+
+  c.li    s4, -13              /* Magic Signature "MZ" (2 bytes) */
+  j       real_start           /* Jump to Kernel Start (2 bytes) */
+  .long   0                    /* Executable Code padded to 8 bytes */
+  .quad   0x0200000            /* Image load offset from start of RAM */
+  .quad   0x4000000            /* Kernel size (fdt_addr_r-kernel_addr_r) */
+  .quad   0                    /* Kernel flags, little-endian */
+  .long   2                    /* Version of this header */
+  .long   0                    /* Reserved */
+  .quad   0                    /* Reserved */
+  .ascii  "RISCV\x00\x00\x00"  /* Magic number, "RISCV" (8 bytes) */
+  .ascii  "RSC\x05"            /* Magic number 2, "RSC\x05" (4 bytes) */
+  .long   0                    /* Reserved for PE COFF offset */
+
+real_start:
+
+  /* Load the number of CPUs that the kernel supports */
+
+#ifdef CONFIG_SMP
+  li   t1, CONFIG_SMP_NCPUS
+#else
+  li   t1, 1
+#endif
+
+  /* Set stack pointer to the idle thread stack. Assume Hart 0. */
+
+  li   a2, 0
+  riscv_set_inital_sp EIC7700X_IDLESTACK_BASE, SMP_STACK_SIZE, a2
+
+  /* Disable all interrupts (i.e. timer, external) in sie */
+
+  csrw CSR_SIE, zero
+
+  la   t0, __trap_vec
+  csrw CSR_STVEC, t0
+
+  /* Jump to eic7700x_start */
+
+  jal  x1, eic7700x_start
+
+  /* We shouldn't return from _start */
+
+  .global _init
+  .global _fini
+
+_init:
+_fini:
+
+  /* These don't have to do anything since we use init_array/fini_array. */
+
+  ret
diff --git a/arch/risc-v/src/eic7700x/eic7700x_irq.c b/arch/risc-v/src/eic7700x/eic7700x_irq.c
new file mode 100644
index 0000000000000..7ef5e525545ec
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_irq.c
@@ -0,0 +1,228 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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 <stdio.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+
+#include "riscv_internal.h"
+#include "riscv_ipi.h"
+#include "chip.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_irqinitialize
+ ****************************************************************************/
+
+void up_irqinitialize(void)
+{
+  uintptr_t addr;
+  uintptr_t claim;
+  int hart;
+  int offset;
+
+  /* Disable S-Mode interrupts */
+
+  up_irq_save();
+
+  /* Attach the common interrupt handler */
+
+  riscv_exception_attach();
+
+  /* Disable all global interrupts */
+
+  for (hart = 0; hart < CONFIG_SMP_NCPUS; hart++)
+    {
+      addr = EIC7700X_PLIC_ENABLE0 + (hart * EIC7700X_PLIC_ENABLE_HART);
+      for (offset = 0; offset < (EIC7700X_PLIC_IRQS) >> 3; offset += 4)
+        {
+          putreg32(0x0, addr + offset);
+        }
+    }
+
+  /* Clear pendings in PLIC */
+
+  for (hart = 0; hart < CONFIG_SMP_NCPUS; hart++)
+    {
+      addr = EIC7700X_PLIC_CLAIM0 + (hart * EIC7700X_PLIC_CLAIM_HART);
+      claim = getreg32(addr);
+      putreg32(claim, addr);
+    }
+
+  /* Colorize the interrupt stack for debug purposes */
+
+#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15
+  size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~15);
+  riscv_stack_color(g_intstackalloc, intstack_size);
+#endif
+
+  /* Set priority for all global interrupts to 1 (lowest) */
+
+  int id;
+
+  for (id = 1; id <= NR_IRQS; id++)
+    {
+      putreg32(1, (uintptr_t)(EIC7700X_PLIC_PRIORITY + 4 * id));
+    }
+
+  /* Set irq threshold to 0 (permits all global interrupts) */
+
+  for (hart = 0; hart < CONFIG_SMP_NCPUS; hart++)
+    {
+      addr = EIC7700X_PLIC_THRESHOLD0 +
+             (hart * EIC7700X_PLIC_THRESHOLD_HART);
+      putreg32(0, addr);
+    }
+
+#ifdef CONFIG_SMP
+  /* Clear IPI for CPU0 */
+
+  riscv_ipi_clear(0);
+
+  up_enable_irq(RISCV_IRQ_SOFT);
+#endif
+
+#ifndef CONFIG_SUPPRESS_INTERRUPTS
+
+  /* And finally, enable interrupts */
+
+  up_irq_enable();
+#endif
+}
+
+/****************************************************************************
+ * Name: up_disable_irq
+ *
+ * Description:
+ *   Disable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_disable_irq(int irq)
+{
+  uintptr_t addr;
+  int extirq;
+
+  if (irq == RISCV_IRQ_SOFT)
+    {
+      /* Read sstatus & clear software interrupt enable in sie */
+
+      CLEAR_CSR(CSR_IE, IE_SIE);
+    }
+  else if (irq == RISCV_IRQ_TIMER)
+    {
+      /* Read sstatus & clear timer interrupt enable in sie */
+
+      CLEAR_CSR(CSR_IE, IE_TIE);
+    }
+  else if (irq > RISCV_IRQ_EXT)
+    {
+      extirq = irq - RISCV_IRQ_EXT;
+
+      /* Clear enable bit for the irq */
+
+      if (0 <= extirq && extirq <= EIC7700X_PLIC_IRQS)
+        {
+          addr = EIC7700X_PLIC_ENABLE0 +
+                 (g_eic7700x_boot_hart * EIC7700X_PLIC_ENABLE_HART);
+          modifyreg32(addr + (4 * (extirq / 32)),
+                      1 << (extirq % 32), 0);
+        }
+      else
+        {
+          PANIC();
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: up_enable_irq
+ *
+ * Description:
+ *   Enable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_enable_irq(int irq)
+{
+  uintptr_t addr;
+  int extirq;
+
+  if (irq == RISCV_IRQ_SOFT)
+    {
+      /* Read sstatus & set software interrupt enable in sie */
+
+      SET_CSR(CSR_IE, IE_SIE);
+    }
+  else if (irq == RISCV_IRQ_TIMER)
+    {
+      /* Read sstatus & set timer interrupt enable in sie */
+
+      SET_CSR(CSR_IE, IE_TIE);
+    }
+  else if (irq > RISCV_IRQ_EXT)
+    {
+      extirq = irq - RISCV_IRQ_EXT;
+
+      /* Set enable bit for the irq */
+
+      if (0 <= extirq && extirq <= EIC7700X_PLIC_IRQS)
+        {
+          addr = EIC7700X_PLIC_ENABLE0 +
+                 (g_eic7700x_boot_hart * EIC7700X_PLIC_ENABLE_HART);
+          modifyreg32(addr + (4 * (extirq / 32)),
+                      0, 1 << (extirq % 32));
+        }
+      else
+        {
+          PANIC();
+        }
+    }
+}
+
+irqstate_t up_irq_enable(void)
+{
+  irqstate_t oldstat;
+
+  /* Enable external interrupts (sie) */
+
+  SET_CSR(CSR_IE, IE_EIE);
+
+  /* Read and enable global interrupts (sie) in sstatus */
+
+  oldstat = READ_AND_SET_CSR(CSR_STATUS, STATUS_IE);
+
+  return oldstat;
+}
diff --git a/arch/risc-v/src/eic7700x/eic7700x_irq_dispatch.c b/arch/risc-v/src/eic7700x/eic7700x_irq_dispatch.c
new file mode 100644
index 0000000000000..8cadae5a8c5e6
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_irq_dispatch.c
@@ -0,0 +1,89 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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 <assert.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <sys/types.h>
+
+#include "riscv_internal.h"
+#include "hardware/eic7700x_memorymap.h"
+#include "hardware/eic7700x_plic.h"
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RV_IRQ_MASK 59
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * riscv_dispatch_irq
+ ****************************************************************************/
+
+void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
+{
+  int irq = (vector >> RV_IRQ_MASK) | (vector & 0xf);
+  uintptr_t claim = EIC7700X_PLIC_CLAIM0 +
+                    (g_eic7700x_boot_hart * EIC7700X_PLIC_CLAIM_HART);
+
+  /* Firstly, check if the irq is machine external interrupt */
+
+  if (RISCV_IRQ_EXT == irq)
+    {
+      uintptr_t val = getreg32(claim);
+
+      /* Add the value to nuttx irq which is offset to the mext */
+
+      irq += val;
+    }
+
+  /* EXT means no interrupt */
+
+  if (RISCV_IRQ_EXT != irq)
+    {
+      /* Deliver the IRQ */
+
+      regs = riscv_doirq(irq, regs);
+    }
+
+  if (RISCV_IRQ_EXT <= irq)
+    {
+      /* Then write PLIC_CLAIM to clear pending in PLIC */
+
+      putreg32(irq - RISCV_IRQ_EXT, claim);
+    }
+
+  return regs;
+}
diff --git a/arch/risc-v/src/eic7700x/eic7700x_memorymap.h b/arch/risc-v/src/eic7700x/eic7700x_memorymap.h
new file mode 100644
index 0000000000000..3ac5d8f4033e0
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_memorymap.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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_EIC7700X_EIC7700X_MEMORYMAP_H
+#define __ARCH_RISCV_SRC_EIC7700X_EIC7700X_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "riscv_common_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Idle thread stack starts from _ebss */
+
+#ifndef __ASSEMBLY__
+#define EIC7700X_IDLESTACK_BASE  (uintptr_t)_ebss
+#else
+#define EIC7700X_IDLESTACK_BASE  _ebss
+#endif
+
+#endif /* __ARCH_RISCV_SRC_EIC7700X_EIC7700X_MEMORYMAP_H */
diff --git a/arch/risc-v/src/eic7700x/eic7700x_mm_init.c b/arch/risc-v/src/eic7700x/eic7700x_mm_init.c
new file mode 100644
index 0000000000000..f9805795803d3
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_mm_init.c
@@ -0,0 +1,274 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_mm_init.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 <nuttx/arch.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/board/board_memorymap.h>
+
+#include "eic7700x_memorymap.h"
+
+#include "riscv_internal.h"
+#include "riscv_mmu.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Map the I/O and PLIC Memory with vaddr = paddr mappings */
+
+#define MMU_IO_BASE      (0x00000000ul)
+#define MMU_IO_SIZE      (0x80000000ul)
+
+/* Physical and virtual addresses to page tables (vaddr = paddr mapping) */
+
+#define PGT_L1_PBASE     (uintptr_t)&m_l1_pgtable
+#define PGT_L2_PBASE     (uintptr_t)&m_l2_pgtable
+#define PGT_L3_PBASE     (uintptr_t)&m_l3_pgtable
+#define PGT_L1_VBASE     PGT_L1_PBASE
+#define PGT_L2_VBASE     PGT_L2_PBASE
+#define PGT_L3_VBASE     PGT_L3_PBASE
+
+#define PGT_L1_SIZE      (512)  /* Enough to map 512 GiB */
+#define PGT_L2_SIZE      (512)  /* Enough to map 1 GiB */
+#define PGT_L3_SIZE      (1024) /* Enough to map 4 MiB (2MiB x 2) */
+
+#define SLAB_COUNT       (sizeof(m_l3_pgtable) / RV_MMU_PAGE_SIZE)
+
+#define KMM_PAGE_SIZE    RV_MMU_L3_PAGE_SIZE
+#define KMM_PBASE        PGT_L3_PBASE
+#define KMM_PBASE_IDX    3
+#define KMM_SPBASE       PGT_L2_PBASE
+#define KMM_SPBASE_IDX   2
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct pgalloc_slab_s
+{
+  sq_entry_t  *next;
+  void        *memory;
+};
+typedef struct pgalloc_slab_s pgalloc_slab_t;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Kernel mappings simply here, mapping is vaddr=paddr */
+
+static size_t m_l1_pgtable[PGT_L1_SIZE] locate_data(".pgtables");
+static size_t m_l2_pgtable[PGT_L2_SIZE] locate_data(".pgtables");
+static size_t m_l3_pgtable[PGT_L3_SIZE] locate_data(".pgtables");
+
+/* Kernel mappings (L1 base) */
+
+uintptr_t g_kernel_mappings  = PGT_L1_VBASE;
+uintptr_t g_kernel_pgt_pbase = PGT_L1_PBASE;
+
+/* L3 page table allocator */
+
+static sq_queue_t     g_free_slabs;
+static pgalloc_slab_t g_slabs[SLAB_COUNT];
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: slab_init
+ *
+ * Description:
+ *   Initialize slab allocator for L2 or L3 page table entries.
+ *   L2 Page table is used for SV32. L3 is used for SV39.
+ *
+ * Input Parameters:
+ *   start - Beginning of the L2 or L3 page table pool
+ *
+ ****************************************************************************/
+
+static void slab_init(uintptr_t start)
+{
+  int i;
+
+  sq_init(&g_free_slabs);
+
+  for (i = 0; i < SLAB_COUNT; i++)
+    {
+      g_slabs[i].memory = (void *)start;
+      sq_addlast((sq_entry_t *)&g_slabs[i], (sq_queue_t *)&g_free_slabs);
+      start += RV_MMU_PAGE_SIZE;
+    }
+}
+
+/****************************************************************************
+ * Name: slab_alloc
+ *
+ * Description:
+ *   Allocate single slab for L2/L3 page table entry.
+ *   L2 Page table is used for SV32. L3 is used for SV39.
+ *
+ ****************************************************************************/
+
+static uintptr_t slab_alloc(void)
+{
+  pgalloc_slab_t *slab = (pgalloc_slab_t *)sq_remfirst(&g_free_slabs);
+  return slab ? (uintptr_t)slab->memory : 0;
+}
+
+/****************************************************************************
+ * Name: map_region
+ *
+ * Description:
+ *   Map a region of physical memory to the L3 page table
+ *
+ * Input Parameters:
+ *   paddr - Beginning of the physical address mapping
+ *   vaddr - Beginning of the virtual address mapping
+ *   size - Size of the region in bytes
+ *   mmuflags - The MMU flags to use in the mapping
+ *
+ ****************************************************************************/
+
+static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size,
+                       uint64_t mmuflags)
+{
+  uintptr_t endaddr;
+  uintptr_t pbase;
+  int npages;
+  int i;
+  int j;
+
+  /* How many pages */
+
+  npages = (size + RV_MMU_PAGE_MASK) >> RV_MMU_PAGE_SHIFT;
+  endaddr = vaddr + size;
+
+  for (i = 0; i < npages; i += RV_MMU_PAGE_ENTRIES)
+    {
+      /* See if a mapping exists */
+
+      pbase = mmu_pte_to_paddr(mmu_ln_getentry(KMM_SPBASE_IDX,
+                                               KMM_SPBASE, vaddr));
+      if (!pbase)
+        {
+          /* No, allocate 1 page, this must not fail */
+
+          pbase = slab_alloc();
+          DEBUGASSERT(pbase);
+
+          /* Map it to the new table */
+
+          mmu_ln_setentry(KMM_SPBASE_IDX, KMM_SPBASE, pbase, vaddr,
+                          MMU_UPGT_FLAGS);
+        }
+
+      /* Then add the mappings */
+
+      for (j = 0; j < RV_MMU_PAGE_ENTRIES && vaddr < endaddr; j++)
+        {
+          mmu_ln_setentry(KMM_PBASE_IDX, pbase, paddr, vaddr, mmuflags);
+          paddr += KMM_PAGE_SIZE;
+          vaddr += KMM_PAGE_SIZE;
+        }
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_kernel_mappings
+ *
+ * Description:
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up the kernel
+ *  MMU mappings.
+ *
+ ****************************************************************************/
+
+void eic7700x_kernel_mappings(void)
+{
+  /* Initialize slab allocator for the L2/L3 page tables */
+
+  slab_init(KMM_PBASE);
+
+  /* Begin mapping memory to MMU; note that at this point the MMU is not yet
+   * active, so the page table virtual addresses are actually physical
+   * addresses and so forth.
+   */
+
+  /* Map I/O region, use enough large page tables for the IO region. */
+
+  binfo("map I/O regions\n");
+  mmu_ln_map_region(1, PGT_L1_VBASE, MMU_IO_BASE, MMU_IO_BASE,
+                    MMU_IO_SIZE, MMU_IO_FLAGS);
+
+  /* Map the kernel text and data for L2/L3 */
+
+  binfo("map kernel text\n");
+  map_region(KFLASH_START, KFLASH_START, KFLASH_SIZE, MMU_KTEXT_FLAGS);
+
+  binfo("map kernel data\n");
+  map_region(KSRAM_START, KSRAM_START, KSRAM_SIZE, MMU_KDATA_FLAGS);
+
+  /* Connect the L1 and L2 page tables for the kernel text and data */
+
+  binfo("connect the L1 and L2 page tables\n");
+  mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_PBASE, KFLASH_START, PTE_G);
+
+  /* Map the page pool */
+
+  binfo("map the page pool\n");
+  mmu_ln_map_region(2, PGT_L2_VBASE, PGPOOL_START, PGPOOL_START,
+                    PGPOOL_SIZE, MMU_KDATA_FLAGS);
+}
+
+/****************************************************************************
+ * Name: eic7700x_mm_init
+ *
+ * Description:
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU
+ *  mappings. Function also sets the first address environment (satp value).
+ *
+ ****************************************************************************/
+
+void eic7700x_mm_init(void)
+{
+  /* Setup the kernel mappings */
+
+  eic7700x_kernel_mappings();
+
+  /* Enable MMU */
+
+  binfo("mmu_enable: satp=%" PRIuPTR "\n", g_kernel_pgt_pbase);
+  mmu_enable(g_kernel_pgt_pbase, 0);
+}
diff --git a/arch/risc-v/src/eic7700x/eic7700x_mm_init.h b/arch/risc-v/src/eic7700x/eic7700x_mm_init.h
new file mode 100644
index 0000000000000..8adcbd02c90f4
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_mm_init.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_mm_init.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_RISC_V_SRC_EIC7700X_EIC7700X_MM_INIT_H
+#define __ARCH_RISC_V_SRC_EIC7700X_EIC7700X_MM_INIT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "riscv_mmu.h"
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_kernel_mappings
+ *
+ * Description:
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up the kernel
+ *  MMU mappings.
+ *
+ ****************************************************************************/
+
+void eic7700x_kernel_mappings(void);
+
+/****************************************************************************
+ * Name: eic7700x_mm_init
+ *
+ * Description:
+ *  Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU
+ *  mappings. Function also sets the first address environment (satp value).
+ *
+ ****************************************************************************/
+
+void eic7700x_mm_init(void);
+
+#endif /* __ARCH_RISC_V_SRC_EIC7700X_EIC7700X_MM_INIT_H */
diff --git a/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c b/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c
new file mode 100644
index 0000000000000..9c7c2b3bb0c66
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_pgalloc.c
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_pgalloc.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/arch.h>
+#include <nuttx/config.h>
+#include <nuttx/pgalloc.h>
+#include <assert.h>
+#include <debug.h>
+#include <arch/board/board_memorymap.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_pgheap
+ *
+ * Description:
+ *   If there is a page allocator in the configuration, then this function
+ *   must be provided by the platform-specific code.  The OS initialization
+ *   logic will call this function early in the initialization sequence to
+ *   get the page heap information needed to configure the page allocator.
+ *
+ ****************************************************************************/
+
+void up_allocate_pgheap(void **heap_start, size_t *heap_size)
+{
+  DEBUGASSERT(heap_start && heap_size);
+
+  *heap_start = (void *)PGPOOL_START;
+  *heap_size  = (size_t)PGPOOL_SIZE;
+}
diff --git a/arch/risc-v/src/eic7700x/eic7700x_start.c b/arch/risc-v/src/eic7700x/eic7700x_start.c
new file mode 100644
index 0000000000000..b10d00c207865
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_start.c
@@ -0,0 +1,431 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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 <nuttx/init.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/uart_16550.h>
+
+#include <debug.h>
+
+#include <arch/board/board.h>
+#include <arch/board/board_memorymap.h>
+
+#include "riscv_internal.h"
+#include "riscv_sbi.h"
+#include "chip.h"
+#include "eic7700x_mm_init.h"
+#include "eic7700x_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_FEATURES
+#define showprogress(c) up_putc(c)
+#else
+#define showprogress(c)
+#endif
+
+/* SBI Extension ID and Function ID for Hart Start */
+
+#define SBI_EXT_HSM 0x0048534D
+#define SBI_EXT_HSM_HART_START 0x0
+
+/****************************************************************************
+ * Extern Function Declarations
+ ****************************************************************************/
+
+extern void __start(void);
+extern void __trap_vec(void);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Hart ID that booted NuttX (0 to 3) */
+
+int g_eic7700x_boot_hart = -1;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_copy_overlap
+ *
+ * Description:
+ *   Copy an overlapping memory region.  dest overlaps with src + count.
+ *
+ * Input Parameters:
+ *   dest  - Destination address
+ *   src   - Source address
+ *   count - Number of bytes to copy
+ *
+ ****************************************************************************/
+
+static void eic7700x_copy_overlap(uint8_t *dest, const uint8_t *src,
+                               size_t count)
+{
+  uint8_t *d = dest + count - 1;
+  const uint8_t *s = src + count - 1;
+
+  if (dest <= src)
+    {
+      _err("dest and src should overlap");
+      PANIC();
+    }
+
+  while (count--)
+    {
+      volatile uint8_t c = *s;  /* Prevent compiler optimization */
+      *d = c;
+      d--;
+      s--;
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_copy_ramdisk
+ *
+ * Description:
+ *   Copy the RAM Disk from NuttX Image to RAM Disk Region.
+ *
+ ****************************************************************************/
+
+static void eic7700x_copy_ramdisk(void)
+{
+  const char *header = "-rom1fs-";
+  const uint8_t *limit = (uint8_t *)g_idle_topstack + (256 * 1024);
+  uint8_t *ramdisk_addr = NULL;
+  uint8_t *addr;
+  uint32_t size;
+
+  /* After _edata, search for "-rom1fs-". This is the RAM Disk Address.
+   * Limit search to 256 KB after Idle Stack Top.
+   */
+
+  binfo("_edata=%p, _sbss=%p, _ebss=%p, idlestack_top=%p\n",
+        (void *)_edata, (void *)_sbss, (void *)_ebss,
+        (void *)g_idle_topstack);
+  for (addr = _edata; addr < limit; addr++)
+    {
+      if (memcmp(addr, header, strlen(header)) == 0)
+        {
+          ramdisk_addr = addr;
+          break;
+        }
+    }
+
+  /* Stop if RAM Disk is missing */
+
+  binfo("ramdisk_addr=%p\n", ramdisk_addr);
+  if (ramdisk_addr == NULL)
+    {
+      _err("Missing RAM Disk. Check the initrd padding.");
+      PANIC();
+    }
+
+  /* RAM Disk must be after Idle Stack, to prevent overwriting */
+
+  if (ramdisk_addr <= (uint8_t *)g_idle_topstack)
+    {
+      const size_t pad = (size_t)g_idle_topstack - (size_t)ramdisk_addr;
+      _err("RAM Disk must be after Idle Stack. Increase initrd padding "
+            "by %ul bytes.", pad);
+      PANIC();
+    }
+
+  /* Read the Filesystem Size from the next 4 bytes (Big Endian) */
+
+  size = (ramdisk_addr[8] << 24) + (ramdisk_addr[9] << 16) +
+         (ramdisk_addr[10] << 8) + ramdisk_addr[11] + 0x1f0;
+  binfo("size=%d\n", size);
+
+  /* Filesystem Size must be less than RAM Disk Memory Region */
+
+  if (size > (size_t)__ramdisk_size)
+    {
+      _err("RAM Disk Region too small. Increase by %ul bytes.\n",
+            size - (size_t)__ramdisk_size);
+      PANIC();
+    }
+
+  /* Copy the RAM Disk from NuttX Image to RAM Disk Region.
+   * __ramdisk_start overlaps with ramdisk_addr + size.
+   */
+
+  eic7700x_copy_overlap(__ramdisk_start, ramdisk_addr, size);
+}
+
+/****************************************************************************
+ * Name: sbi_ecall
+ *
+ * Description:
+ *   Make a RISC-V ECALL to OpenSBI.
+ *
+ * Input Parameters:
+ *   extid          - Extension ID
+ *   fid            - Function ID
+ *   parm0 to parm5 - Parameters to be passed
+ *
+ * Returned Value:
+ *   Error and Value returned by OpenSBI.
+ *
+ ****************************************************************************/
+
+static sbiret_t sbi_ecall(unsigned int extid, unsigned int fid,
+                          uintreg_t parm0, uintreg_t parm1,
+                          uintreg_t parm2, uintreg_t parm3,
+                          uintreg_t parm4, uintreg_t parm5)
+{
+  register long r0 asm("a0") = (long)(parm0);
+  register long r1 asm("a1") = (long)(parm1);
+  register long r2 asm("a2") = (long)(parm2);
+  register long r3 asm("a3") = (long)(parm3);
+  register long r4 asm("a4") = (long)(parm4);
+  register long r5 asm("a5") = (long)(parm5);
+  register long r6 asm("a6") = (long)(fid);
+  register long r7 asm("a7") = (long)(extid);
+  sbiret_t ret;
+
+  asm volatile
+    (
+     "ecall"
+     : "+r"(r0), "+r"(r1)
+     : "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
+     : "memory"
+     );
+
+  ret.error = r0;
+  ret.value = (uintreg_t)r1;
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: boot_secondary
+ *
+ * Description:
+ *   Call OpenSBI to boot the Hart, starting at the specified address.
+ *
+ * Input Parameters:
+ *   hartid - Hart ID
+ *   addr   - Start Address
+ *
+ * Returned Value:
+ *   OK is always returned.
+ *
+ ****************************************************************************/
+
+static int boot_secondary(uintreg_t hartid, uintreg_t addr)
+{
+  sbiret_t ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
+                          hartid, addr, 0, 0, 0, 0);
+
+  if (ret.error < 0)
+    {
+      _err("Boot Hart %d failed\n", hartid);
+      PANIC();
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_clear_bss
+ *
+ * Description:
+ *   Clear .bss.  We'll do this inline (vs. calling memset) just to be
+ *   certain that there are no issues with the state of global variables.
+ *
+ ****************************************************************************/
+
+void eic7700x_clear_bss(void)
+{
+  uint32_t *dest;
+
+  for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; )
+    {
+      *dest++ = 0;
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_start_s
+ *
+ * Description:
+ *   Start the NuttX Kernel.  Assume that we are in RISC-V Supervisor Mode.
+ *
+ * Input Parameters:
+ *   mhartid - Hart ID
+ *
+ ****************************************************************************/
+
+void eic7700x_start_s(int mhartid)
+{
+  /* Configure FPU */
+
+  riscv_fpuconfig();
+
+  if (mhartid != g_eic7700x_boot_hart)
+    {
+      goto cpux;
+    }
+
+  /* Boot Hart starts here. Init the UART Driver. */
+
+  showprogress('A');
+
+#ifdef USE_EARLYSERIALINIT
+  riscv_earlyserialinit();
+#endif
+
+  /* Setup page tables for kernel and enable MMU */
+
+  showprogress('B');
+  eic7700x_mm_init();
+
+  /* Start NuttX */
+
+  showprogress('C');
+  nx_start();
+
+cpux:
+
+  /* Non-Boot Hart starts here. Init the CPU for the Hart. */
+
+#ifdef CONFIG_SMP
+  riscv_cpu_boot(mhartid);
+#endif
+
+  while (true)
+    {
+      asm("WFI");
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_start
+ *
+ * Description:
+ *   Start the NuttX Kernel.  Called by Boot Code.
+ *
+ * Input Parameters:
+ *   mhartid - Hart ID
+ *
+ ****************************************************************************/
+
+void eic7700x_start(int mhartid)
+{
+  /* If Boot Hart is not 0, restart with Hart 0 */
+
+  if (mhartid != 0)
+    {
+      /* Clear the BSS */
+
+      eic7700x_clear_bss();
+
+      /* Restart with Hart 0 */
+
+      boot_secondary(0, (uintptr_t)&__start);
+
+      /* Let this Hart idle forever */
+
+      while (true)
+        {
+          asm("WFI");
+        }
+
+      PANIC(); /* Should not come here */
+    }
+
+  /* Init the globals once only. Remember the Boot Hart. */
+
+  if (g_eic7700x_boot_hart < 0)
+    {
+      g_eic7700x_boot_hart = mhartid;
+
+      /* Clear the BSS */
+
+      eic7700x_clear_bss();
+
+      /* Copy the RAM Disk */
+
+      eic7700x_copy_ramdisk();
+
+      /* Initialize the per CPU areas */
+
+      riscv_percpu_add_hart(mhartid);
+    }
+
+  /* Disable MMU */
+
+  WRITE_CSR(CSR_SATP, 0x0);
+
+  /* Set the trap vector for S-mode */
+
+  WRITE_CSR(CSR_STVEC, (uintptr_t)__trap_vec);
+
+  /* Start S-mode */
+
+  eic7700x_start_s(mhartid);
+}
+
+/****************************************************************************
+ * Name: riscv_earlyserialinit
+ *
+ * Description:
+ *   Performs the low level UART initialization early in debug so that the
+ *   serial console will be available during bootup.  This must be called
+ *   before riscv_serialinit.  NOTE:  This function depends on GPIO pin
+ *   configuration performed in up_consoleinit() and main clock
+ *   initialization performed in up_clkinitialize().
+ *
+ ****************************************************************************/
+
+void riscv_earlyserialinit(void)
+{
+  u16550_earlyserialinit();
+}
+
+/****************************************************************************
+ * Name: riscv_serialinit
+ *
+ * Description:
+ *   Register serial console and serial ports.  This assumes
+ *   that riscv_earlyserialinit was called previously.
+ *
+ ****************************************************************************/
+
+void riscv_serialinit(void)
+{
+  u16550_serialinit();
+}
diff --git a/arch/risc-v/src/eic7700x/eic7700x_timerisr.c b/arch/risc-v/src/eic7700x/eic7700x_timerisr.c
new file mode 100644
index 0000000000000..00e5421c6e0f2
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/eic7700x_timerisr.c
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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 <stdint.h>
+#include <time.h>
+#include <debug.h>
+
+#include <nuttx/timers/arch_alarm.h>
+
+#include "riscv_internal.h"
+#include "riscv_mtimer.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+ #define MTIMER_FREQ 1000000ul
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_timer_initialize
+ *
+ * Description:
+ *   This function is called during start-up to initialize
+ *   the timer interrupt.
+ *
+ ****************************************************************************/
+
+void up_timer_initialize(void)
+{
+  struct oneshot_lowerhalf_s *lower;
+
+  /* Initialize the OpenSBI Timer. mtime and mtimecmp are unused for
+   * OpenSBI.
+   */
+
+  lower = riscv_mtimer_initialize(0, 0, RISCV_IRQ_STIMER, MTIMER_FREQ);
+
+  DEBUGASSERT(lower != NULL);
+
+  up_alarm_set_lowerhalf(lower);
+}
diff --git a/arch/risc-v/src/eic7700x/hardware/eic7700x_memorymap.h b/arch/risc-v/src/eic7700x/hardware/eic7700x_memorymap.h
new file mode 100644
index 0000000000000..8d4ab93544909
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/hardware/eic7700x_memorymap.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/hardware/eic7700x_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_EIC7700X_HARDWARE_EIC7700X_MEMORYMAP_H
+#define __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_MEMORYMAP_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register Base Address ****************************************************/
+
+#define EIC7700X_PLIC_BASE 0x0C000000ul
+
+#endif /* __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_MEMORYMAP_H */
diff --git a/arch/risc-v/src/eic7700x/hardware/eic7700x_plic.h b/arch/risc-v/src/eic7700x/hardware/eic7700x_plic.h
new file mode 100644
index 0000000000000..0c9927a7bfebf
--- /dev/null
+++ b/arch/risc-v/src/eic7700x/hardware/eic7700x_plic.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/hardware/eic7700x_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_EIC7700X_HARDWARE_EIC7700X_PLIC_H
+#define __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_PLIC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Interrupt Priority */
+
+#define EIC7700X_PLIC_PRIORITY (EIC7700X_PLIC_BASE + 0x000000)
+
+/* Hart 0 S-Mode Interrupt Enable */
+
+#define EIC7700X_PLIC_ENABLE0     (EIC7700X_PLIC_BASE + 0x002080)
+#define EIC7700X_PLIC_ENABLE_HART 0x100
+
+/* Hart 0 S-Mode Priority Threshold */
+
+#define EIC7700X_PLIC_THRESHOLD0     (EIC7700X_PLIC_BASE + 0x201000)
+#define EIC7700X_PLIC_THRESHOLD_HART 0x2000
+
+/* Hart 0 S-Mode Claim / Complete */
+
+#define EIC7700X_PLIC_CLAIM0     (EIC7700X_PLIC_BASE + 0x201004)
+#define EIC7700X_PLIC_CLAIM_HART 0x2000
+
+#endif /* __ARCH_RISCV_SRC_EIC7700X_HARDWARE_EIC7700X_PLIC_H */


Reviews:
user: login: cederom
body: Thank you @lupyuen Amazing Work!! =)
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T03:41:35Z
user: login: hartmannathan
body: Thanks for adding new arch support! Commit logs look good. Code is well-commented. I don't have this hardware to verify actual code but looks good on code reading.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T14:55:30Z
user: login: lupyuen
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-02T15:35:01Z
user: login: lupyuen
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-02T15:35:15Z
user: login: lupyuen
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-02T15:35:29Z
user: login: lupyuen
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-02T15:40:43Z
user: login: acassis
body: Nice work Lup!!!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T14:13:11Z
user: login: jerpelea
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:01:15Z
user: login: hartmannathan
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T14:27:29Z

Review comments:
diff_hunk: @@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/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_EIC7700X_CHIP_H
+#define __ARCH_RISCV_SRC_EIC7700X_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/* Include the chip capabilities file */
+
+#include <arch/eic7700x/chip.h>
+
+#include "eic7700x_memorymap.h"
+
+#include "hardware/eic7700x_memorymap.h"
+#include "hardware/eic7700x_plic.h"
+
+#include "riscv_internal.h"
+#include "riscv_percpu.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Hart ID that booted NuttX (0 to 3) */
+
+#ifndef __ASSEMBLY__
+extern int g_eic7700x_boot_hart;
+#endif
+
+/****************************************************************************
+ * Macro Definitions
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+
+/****************************************************************************
+ * Name: setintstack
+ *
+ * Description:
+ *   Set the current stack pointer to the  "top" the correct interrupt stack
path: arch/risc-v/src/eic7700x/chip.h
user: login: hartmannathan
body: ```suggestion
 *   Set the current stack pointer to the  "top" of the correct interrupt stack
```

I think missing "of" here?
created_at: 2025-03-02T14:42:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_allocateheap.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 <nuttx/kmalloc.h>
+#include <nuttx/userspace.h>
+#include <nuttx/arch.h>
+#include <arch/board/board_memorymap.h>
+#include "riscv_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define KRAM_END    KSRAM_END
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, user-space heap.
+ *
+ *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   allocated (and protected) by an analogous up_allocate_kheap().
+ *
+ *   The following memory map is assumed for the flat build:
+ *
+ *   .data region.  Size determined at link time.
+ *   .bss  region  Size determined at link time.
+ *   IDLE thread stack.  Size determined by CONFIG_IDLETHREAD_STACKSIZE.
+ *   Heap.  Extends to the end of User SRAM.
+ *
+ *   The following memory map is assumed for the protect build.
path: arch/risc-v/src/eic7700x/eic7700x_allocateheap.c
user: login: hartmannathan
body: ```suggestion
 *   The following memory map is assumed for the protected build.
```

created_at: 2025-03-02T14:44:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_allocateheap.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 <nuttx/kmalloc.h>
+#include <nuttx/userspace.h>
+#include <nuttx/arch.h>
+#include <arch/board/board_memorymap.h>
+#include "riscv_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define KRAM_END    KSRAM_END
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, user-space heap.
+ *
+ *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   allocated (and protected) by an analogous up_allocate_kheap().
+ *
+ *   The following memory map is assumed for the flat build:
+ *
+ *   .data region.  Size determined at link time.
+ *   .bss  region  Size determined at link time.
+ *   IDLE thread stack.  Size determined by CONFIG_IDLETHREAD_STACKSIZE.
+ *   Heap.  Extends to the end of User SRAM.
+ *
+ *   The following memory map is assumed for the protect build.
+ *   The kernel and user space have it's own dedicated heap space.
path: arch/risc-v/src/eic7700x/eic7700x_allocateheap.c
user: login: hartmannathan
body: ```suggestion
 *   The kernel and user space have their own dedicated heap spaces.
```

created_at: 2025-03-02T14:44:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,433 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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 <nuttx/init.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/uart_16550.h>
+
+#include <debug.h>
+
+#include <arch/board/board.h>
+#include <arch/board/board_memorymap.h>
+
+#include "riscv_internal.h"
+#include "riscv_sbi.h"
+#include "chip.h"
+#include "eic7700x_mm_init.h"
+#include "eic7700x_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_FEATURES
+#define showprogress(c) up_putc(c)
+#else
+#define showprogress(c)
+#endif
+
+/* SBI Extension ID and Function ID for Hart Start */
+
+#define SBI_EXT_HSM 0x0048534D
+#define SBI_EXT_HSM_HART_START 0x0
+
+/****************************************************************************
+ * Extern Function Declarations
+ ****************************************************************************/
+
+extern void __start(void);
+extern void __trap_vec(void);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Hart ID that booted NuttX (0 to 3) */
+
+int g_eic7700x_boot_hart = -1;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_copy_overlap
+ *
+ * Description:
+ *   Copy an overlapping memory region.  dest overlaps with src + count.
+ *
+ * Input Parameters:
+ *   dest  - Destination address
+ *   src   - Source address
+ *   count - Number of bytes to copy
+ *
+ ****************************************************************************/
+
+static void eic7700x_copy_overlap(uint8_t *dest, const uint8_t *src,
+                               size_t count)
+{
+  uint8_t *d = dest + count - 1;
+  const uint8_t *s = src + count - 1;
+
+  if (dest <= src)
+    {
+      _err("dest and src should overlap");
+      PANIC();
+    }
+
+  while (count--)
+    {
+      volatile uint8_t c = *s;  /* Prevent compiler optimization */
+      *d = c;
+      d--;
+      s--;
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_copy_ramdisk
+ *
+ * Description:
+ *   Copy the RAM Disk from NuttX Image to RAM Disk Region.
+ *
+ ****************************************************************************/
+
+static void eic7700x_copy_ramdisk(void)
+{
+  const char *header = "-rom1fs-";
+  const uint8_t *limit = (uint8_t *)g_idle_topstack + (256 * 1024);
+  uint8_t *ramdisk_addr = NULL;
+  uint8_t *addr;
+  uint32_t size;
+
+  /* After _edata, search for "-rom1fs-". This is the RAM Disk Address.
+   * Limit search to 256 KB after Idle Stack Top.
+   */
+
+  binfo("_edata=%p, _sbss=%p, _ebss=%p, idlestack_top=%p\n",
+        (void *)_edata, (void *)_sbss, (void *)_ebss,
+        (void *)g_idle_topstack);
+  for (addr = _edata; addr < limit; addr++)
+    {
+      if (memcmp(addr, header, strlen(header)) == 0)
+        {
+          ramdisk_addr = addr;
+          break;
+        }
+    }
+
+  /* Stop if RAM Disk is missing */
+
+  binfo("ramdisk_addr=%p\n", ramdisk_addr);
+  if (ramdisk_addr == NULL)
+    {
+      _err("Missing RAM Disk. Check the initrd padding.");
+      PANIC();
+    }
+
+  /* RAM Disk must be after Idle Stack, to prevent overwriting */
+
+  if (ramdisk_addr <= (uint8_t *)g_idle_topstack)
+    {
+      const size_t pad = (size_t)g_idle_topstack - (size_t)ramdisk_addr;
+      _err("RAM Disk must be after Idle Stack. Increase initrd padding "
+            "by %ul bytes.", pad);
+      PANIC();
+    }
+
+  /* Read the Filesystem Size from the next 4 bytes (Big Endian) */
+
+  size = (ramdisk_addr[8] << 24) + (ramdisk_addr[9] << 16) +
+         (ramdisk_addr[10] << 8) + ramdisk_addr[11] + 0x1f0;
+  binfo("size=%d\n", size);
+
+  /* Filesystem Size must be less than RAM Disk Memory Region */
+
+  if (size > (size_t)__ramdisk_size)
+    {
+      _err("RAM Disk Region too small. Increase by %ul bytes.\n",
+            size - (size_t)__ramdisk_size);
+      PANIC();
+    }
+
+  /* Copy the RAM Disk from NuttX Image to RAM Disk Region.
+   * __ramdisk_start overlaps with ramdisk_addr + size.
+   */
+
+  eic7700x_copy_overlap(__ramdisk_start, ramdisk_addr, size);
+}
+
+/****************************************************************************
+ * Name: sbi_ecall
+ *
+ * Description:
+ *   Make a RISC-V ECALL to OpenSBI.
+ *
+ * Input Parameters:
+ *   extid          - Extension ID
+ *   fid            - Function ID
+ *   parm0 to parm5 - Parameters to be passed
+ *
+ * Returned Value:
+ *   Error and Value returned by OpenSBI.
+ *
+ ****************************************************************************/
+
+static sbiret_t sbi_ecall(unsigned int extid, unsigned int fid,
+                          uintreg_t parm0, uintreg_t parm1,
+                          uintreg_t parm2, uintreg_t parm3,
+                          uintreg_t parm4, uintreg_t parm5)
+{
+  register long r0 asm("a0") = (long)(parm0);
+  register long r1 asm("a1") = (long)(parm1);
+  register long r2 asm("a2") = (long)(parm2);
+  register long r3 asm("a3") = (long)(parm3);
+  register long r4 asm("a4") = (long)(parm4);
+  register long r5 asm("a5") = (long)(parm5);
+  register long r6 asm("a6") = (long)(fid);
+  register long r7 asm("a7") = (long)(extid);
+  sbiret_t ret;
+
+  asm volatile
+    (
+     "ecall"
+     : "+r"(r0), "+r"(r1)
+     : "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
+     : "memory"
+     );
+
+  ret.error = r0;
+  ret.value = (uintreg_t)r1;
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: boot_secondary
+ *
+ * Description:
+ *   Call OpenSBI to boot the Hart, starting at the specified address.
+ *
+ * Input Parameters:
+ *   hartid - Hart ID
+ *   addr   - Start Address
+ *
+ * Returned Value:
+ *   OK is always returned.
+ *
+ ****************************************************************************/
+
+static int boot_secondary(uintreg_t hartid, uintreg_t addr)
+{
+  sbiret_t ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
+                          hartid, addr, 0, 0, 0, 0);
+
+  if (ret.error < 0)
+    {
+      _err("Boot Hart %d failed\n", hartid);
+      PANIC();
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_clear_bss
+ *
+ * Description:
+ *   Clear .bss.  We'll do this inline (vs. calling memset) just to be
+ *   certain that there are no issues with the state of global variables.
+ *
+ ****************************************************************************/
+
+void eic7700x_clear_bss(void)
+{
+  uint32_t *dest;
+
+  for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; )
+    {
+      *dest++ = 0;
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_start_s
+ *
+ * Description:
+ *   Start the NuttX Kernel.  Assume that we are in RISC-V Supervisor Mode.
+ *
+ * Input Parameters:
+ *   mhartid - Hart ID
+ *
+ ****************************************************************************/
+
+void eic7700x_start_s(int mhartid)
+{
+  /* Configure FPU */
+
+  riscv_fpuconfig();
+
+  if (mhartid != g_eic7700x_boot_hart)
+    {
+      goto cpux;
+    }
+
+  /* Boot Hart starts here */
+
+  showprogress('A');
+
+#ifdef USE_EARLYSERIALINIT
+  riscv_earlyserialinit();
+#endif
+
+  showprogress('B');
+
+  /* Do board initialization */
path: arch/risc-v/src/eic7700x/eic7700x_start.c
user: login: hartmannathan
body: I assume a follow-up PR will actually call board initialization here?
created_at: 2025-03-02T14:52:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/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_EIC7700X_CHIP_H
+#define __ARCH_RISCV_SRC_EIC7700X_CHIP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/* Include the chip capabilities file */
+
+#include <arch/eic7700x/chip.h>
+
+#include "eic7700x_memorymap.h"
+
+#include "hardware/eic7700x_memorymap.h"
+#include "hardware/eic7700x_plic.h"
+
+#include "riscv_internal.h"
+#include "riscv_percpu.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Hart ID that booted NuttX (0 to 3) */
+
+#ifndef __ASSEMBLY__
+extern int g_eic7700x_boot_hart;
+#endif
+
+/****************************************************************************
+ * Macro Definitions
+ ****************************************************************************/
+
+#ifdef __ASSEMBLY__
+
+/****************************************************************************
+ * Name: setintstack
+ *
+ * Description:
+ *   Set the current stack pointer to the  "top" the correct interrupt stack
path: arch/risc-v/src/eic7700x/chip.h
user: login: lupyuen
body: @hartmannathan Fixed, thanks :-)
https://github.com/apache/nuttx/blob/b92f051e337d095491f8406b2d99fdd2f6fa5b3e/arch/risc-v/src/eic7700x/chip.h#L62-L63
created_at: 2025-03-02T15:35:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_allocateheap.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 <nuttx/kmalloc.h>
+#include <nuttx/userspace.h>
+#include <nuttx/arch.h>
+#include <arch/board/board_memorymap.h>
+#include "riscv_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define KRAM_END    KSRAM_END
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, user-space heap.
+ *
+ *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   allocated (and protected) by an analogous up_allocate_kheap().
+ *
+ *   The following memory map is assumed for the flat build:
+ *
+ *   .data region.  Size determined at link time.
+ *   .bss  region  Size determined at link time.
+ *   IDLE thread stack.  Size determined by CONFIG_IDLETHREAD_STACKSIZE.
+ *   Heap.  Extends to the end of User SRAM.
+ *
+ *   The following memory map is assumed for the protect build.
path: arch/risc-v/src/eic7700x/eic7700x_allocateheap.c
user: login: lupyuen
body: @hartmannathan Fixed, thanks :-)
https://github.com/apache/nuttx/blob/b92f051e337d095491f8406b2d99fdd2f6fa5b3e/arch/risc-v/src/eic7700x/eic7700x_allocateheap.c#L68-L69
created_at: 2025-03-02T15:35:15Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,87 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_allocateheap.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 <nuttx/kmalloc.h>
+#include <nuttx/userspace.h>
+#include <nuttx/arch.h>
+#include <arch/board/board_memorymap.h>
+#include "riscv_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define KRAM_END    KSRAM_END
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_allocate_heap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and
+ *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, user-space heap.
+ *
+ *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   allocated (and protected) by an analogous up_allocate_kheap().
+ *
+ *   The following memory map is assumed for the flat build:
+ *
+ *   .data region.  Size determined at link time.
+ *   .bss  region  Size determined at link time.
+ *   IDLE thread stack.  Size determined by CONFIG_IDLETHREAD_STACKSIZE.
+ *   Heap.  Extends to the end of User SRAM.
+ *
+ *   The following memory map is assumed for the protect build.
+ *   The kernel and user space have it's own dedicated heap space.
path: arch/risc-v/src/eic7700x/eic7700x_allocateheap.c
user: login: lupyuen
body: @hartmannathan Fixed, thanks :-)
https://github.com/apache/nuttx/blob/b92f051e337d095491f8406b2d99fdd2f6fa5b3e/arch/risc-v/src/eic7700x/eic7700x_allocateheap.c#L68-L69
created_at: 2025-03-02T15:35:29Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,433 @@
+/****************************************************************************
+ * arch/risc-v/src/eic7700x/eic7700x_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 <nuttx/init.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/uart_16550.h>
+
+#include <debug.h>
+
+#include <arch/board/board.h>
+#include <arch/board/board_memorymap.h>
+
+#include "riscv_internal.h"
+#include "riscv_sbi.h"
+#include "chip.h"
+#include "eic7700x_mm_init.h"
+#include "eic7700x_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_FEATURES
+#define showprogress(c) up_putc(c)
+#else
+#define showprogress(c)
+#endif
+
+/* SBI Extension ID and Function ID for Hart Start */
+
+#define SBI_EXT_HSM 0x0048534D
+#define SBI_EXT_HSM_HART_START 0x0
+
+/****************************************************************************
+ * Extern Function Declarations
+ ****************************************************************************/
+
+extern void __start(void);
+extern void __trap_vec(void);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Hart ID that booted NuttX (0 to 3) */
+
+int g_eic7700x_boot_hart = -1;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_copy_overlap
+ *
+ * Description:
+ *   Copy an overlapping memory region.  dest overlaps with src + count.
+ *
+ * Input Parameters:
+ *   dest  - Destination address
+ *   src   - Source address
+ *   count - Number of bytes to copy
+ *
+ ****************************************************************************/
+
+static void eic7700x_copy_overlap(uint8_t *dest, const uint8_t *src,
+                               size_t count)
+{
+  uint8_t *d = dest + count - 1;
+  const uint8_t *s = src + count - 1;
+
+  if (dest <= src)
+    {
+      _err("dest and src should overlap");
+      PANIC();
+    }
+
+  while (count--)
+    {
+      volatile uint8_t c = *s;  /* Prevent compiler optimization */
+      *d = c;
+      d--;
+      s--;
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_copy_ramdisk
+ *
+ * Description:
+ *   Copy the RAM Disk from NuttX Image to RAM Disk Region.
+ *
+ ****************************************************************************/
+
+static void eic7700x_copy_ramdisk(void)
+{
+  const char *header = "-rom1fs-";
+  const uint8_t *limit = (uint8_t *)g_idle_topstack + (256 * 1024);
+  uint8_t *ramdisk_addr = NULL;
+  uint8_t *addr;
+  uint32_t size;
+
+  /* After _edata, search for "-rom1fs-". This is the RAM Disk Address.
+   * Limit search to 256 KB after Idle Stack Top.
+   */
+
+  binfo("_edata=%p, _sbss=%p, _ebss=%p, idlestack_top=%p\n",
+        (void *)_edata, (void *)_sbss, (void *)_ebss,
+        (void *)g_idle_topstack);
+  for (addr = _edata; addr < limit; addr++)
+    {
+      if (memcmp(addr, header, strlen(header)) == 0)
+        {
+          ramdisk_addr = addr;
+          break;
+        }
+    }
+
+  /* Stop if RAM Disk is missing */
+
+  binfo("ramdisk_addr=%p\n", ramdisk_addr);
+  if (ramdisk_addr == NULL)
+    {
+      _err("Missing RAM Disk. Check the initrd padding.");
+      PANIC();
+    }
+
+  /* RAM Disk must be after Idle Stack, to prevent overwriting */
+
+  if (ramdisk_addr <= (uint8_t *)g_idle_topstack)
+    {
+      const size_t pad = (size_t)g_idle_topstack - (size_t)ramdisk_addr;
+      _err("RAM Disk must be after Idle Stack. Increase initrd padding "
+            "by %ul bytes.", pad);
+      PANIC();
+    }
+
+  /* Read the Filesystem Size from the next 4 bytes (Big Endian) */
+
+  size = (ramdisk_addr[8] << 24) + (ramdisk_addr[9] << 16) +
+         (ramdisk_addr[10] << 8) + ramdisk_addr[11] + 0x1f0;
+  binfo("size=%d\n", size);
+
+  /* Filesystem Size must be less than RAM Disk Memory Region */
+
+  if (size > (size_t)__ramdisk_size)
+    {
+      _err("RAM Disk Region too small. Increase by %ul bytes.\n",
+            size - (size_t)__ramdisk_size);
+      PANIC();
+    }
+
+  /* Copy the RAM Disk from NuttX Image to RAM Disk Region.
+   * __ramdisk_start overlaps with ramdisk_addr + size.
+   */
+
+  eic7700x_copy_overlap(__ramdisk_start, ramdisk_addr, size);
+}
+
+/****************************************************************************
+ * Name: sbi_ecall
+ *
+ * Description:
+ *   Make a RISC-V ECALL to OpenSBI.
+ *
+ * Input Parameters:
+ *   extid          - Extension ID
+ *   fid            - Function ID
+ *   parm0 to parm5 - Parameters to be passed
+ *
+ * Returned Value:
+ *   Error and Value returned by OpenSBI.
+ *
+ ****************************************************************************/
+
+static sbiret_t sbi_ecall(unsigned int extid, unsigned int fid,
+                          uintreg_t parm0, uintreg_t parm1,
+                          uintreg_t parm2, uintreg_t parm3,
+                          uintreg_t parm4, uintreg_t parm5)
+{
+  register long r0 asm("a0") = (long)(parm0);
+  register long r1 asm("a1") = (long)(parm1);
+  register long r2 asm("a2") = (long)(parm2);
+  register long r3 asm("a3") = (long)(parm3);
+  register long r4 asm("a4") = (long)(parm4);
+  register long r5 asm("a5") = (long)(parm5);
+  register long r6 asm("a6") = (long)(fid);
+  register long r7 asm("a7") = (long)(extid);
+  sbiret_t ret;
+
+  asm volatile
+    (
+     "ecall"
+     : "+r"(r0), "+r"(r1)
+     : "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
+     : "memory"
+     );
+
+  ret.error = r0;
+  ret.value = (uintreg_t)r1;
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: boot_secondary
+ *
+ * Description:
+ *   Call OpenSBI to boot the Hart, starting at the specified address.
+ *
+ * Input Parameters:
+ *   hartid - Hart ID
+ *   addr   - Start Address
+ *
+ * Returned Value:
+ *   OK is always returned.
+ *
+ ****************************************************************************/
+
+static int boot_secondary(uintreg_t hartid, uintreg_t addr)
+{
+  sbiret_t ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
+                          hartid, addr, 0, 0, 0, 0);
+
+  if (ret.error < 0)
+    {
+      _err("Boot Hart %d failed\n", hartid);
+      PANIC();
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: eic7700x_clear_bss
+ *
+ * Description:
+ *   Clear .bss.  We'll do this inline (vs. calling memset) just to be
+ *   certain that there are no issues with the state of global variables.
+ *
+ ****************************************************************************/
+
+void eic7700x_clear_bss(void)
+{
+  uint32_t *dest;
+
+  for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; )
+    {
+      *dest++ = 0;
+    }
+}
+
+/****************************************************************************
+ * Name: eic7700x_start_s
+ *
+ * Description:
+ *   Start the NuttX Kernel.  Assume that we are in RISC-V Supervisor Mode.
+ *
+ * Input Parameters:
+ *   mhartid - Hart ID
+ *
+ ****************************************************************************/
+
+void eic7700x_start_s(int mhartid)
+{
+  /* Configure FPU */
+
+  riscv_fpuconfig();
+
+  if (mhartid != g_eic7700x_boot_hart)
+    {
+      goto cpux;
+    }
+
+  /* Boot Hart starts here */
+
+  showprogress('A');
+
+#ifdef USE_EARLYSERIALINIT
+  riscv_earlyserialinit();
+#endif
+
+  showprogress('B');
+
+  /* Do board initialization */
path: arch/risc-v/src/eic7700x/eic7700x_start.c
user: login: lupyuen
body: @hartmannathan Oops I shouldn't have copied it blindly from QEMU RISC-V (which doesn't call board init either):

https://github.com/apache/nuttx/blob/3dde10adaa14e123652cac9c6700296a30a002ab/arch/risc-v/src/qemu-rv/qemu_rv_start.c#L191-L203

So I rewrote the code to make it more sensible:

https://github.com/apache/nuttx/blob/b92f051e337d095491f8406b2d99fdd2f6fa5b3e/arch/risc-v/src/eic7700x/eic7700x_start.c#L302-L328
created_at: 2025-03-02T15:40:43Z
author_association: MEMBER

PR comments:
user: login: nuttxpr
created_at: 2025-03-02T02:08:02Z
body: [**\[Experimental Bot, please feedback here\]**](https://github.com/search?q=repo%3Aapache%2Fnuttx+13552&type=issues)



Yes, this PR meets the NuttX requirements.  The summary clearly explains the change, its purpose, and the affected files. The impact section adequately addresses the scope of the changes and confirms no impact on existing users, build processes, or other hardware. The testing section provides sufficient evidence of successful testing on the target hardware, including boot logs and the output of key commands like `uname`, `free`, `ls`, `ps`, `hello`, `getprime`, and `ostest`. The links to the board source code and build log are also helpful.  The documentation update is mentioned, which is important.  Overall, it's a well-structured and informative PR description.

author_association: NONE
user: login: cederom
created_at: 2025-03-02T19:58:53Z
body: Maybe we should mark this change with `[EXPERIMENTAL]` tag? Its the initial code and will be probably changed often? :-)
author_association: CONTRIBUTOR
user: login: lupyuen
created_at: 2025-03-02T22:00:28Z
body: Actually the typos we found above are also present in other RISC-V ports: QEMU, SG2000, BL808, K230, MPFS, ... So it's not an "Experimental" issue, more like a "Legacy" fix that needs backporting 😬

Update: I found 20 source files with the same typos, I submitted the PR here:
- https://github.com/apache/nuttx/pull/15922
author_association: MEMBER
user: login: lupyuen
created_at: 2025-03-04T13:12:48Z
body: Sorry @hartmannathan: Are you OK if we merge the PR for ESWIN EIC7700X SoC? I corrected the typos (also for 20 other files). Thanks :-)
author_association: MEMBER
user: login: hartmannathan
created_at: 2025-03-04T14:29:08Z
body: > Sorry @hartmannathan: Are you OK if we merge the PR for ESWIN EIC7700X SoC? I corrected the typos (also for 20 other files). Thanks :-)

@lupyuen Yes! LGTM, thanks for your patience, I merged it just now :-)
author_association: CONTRIBUTOR