You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2021/02/08 08:30:10 UTC

[incubator-nuttx] branch master updated: arch:risc-v:bl602: enable FPU for this target.

This is an automated email from the ASF dual-hosted git repository.

btashton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 84daebf  arch:risc-v:bl602: enable FPU for this target.
84daebf is described below

commit 84daebf2ccd2d38d75cdfdfd504f4860efca90ba
Author: hotislandn <ho...@hotmail.com>
AuthorDate: Fri Feb 5 14:29:10 2021 +0800

    arch:risc-v:bl602: enable FPU for this target.
---
 arch/risc-v/Kconfig                                |   1 +
 arch/risc-v/include/csr.h                          |  11 ++-
 arch/risc-v/src/bl602/Make.defs                    |   4 +
 arch/risc-v/src/bl602/bl602_irq.c                  |   4 +
 arch/risc-v/src/bl602/bl602_irq_dispatch.c         |  28 ++++++
 arch/risc-v/src/rv32im/riscv_copystate.c           |  15 ++-
 boards/risc-v/bl602/bl602evb/configs/fpu/defconfig |  77 ++++++++++++++++
 boards/risc-v/bl602/bl602evb/src/Makefile          |   4 +
 .../risc-v/bl602/bl602evb/src/bl602_ostest.c       | 101 +++++++++------------
 9 files changed, 182 insertions(+), 63 deletions(-)

diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 290fd35..3a3bdaa 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -47,6 +47,7 @@ config ARCH_CHIP_GAP8
 config ARCH_CHIP_BL602
 	bool "BouffaloLab BL602"
 	select ARCH_RV32IM
+	select ARCH_HAVE_FPU
 	select ARCH_HAVE_RESET
 	---help---
 		BouffaloLab BL602(rv32imfc)
diff --git a/arch/risc-v/include/csr.h b/arch/risc-v/include/csr.h
index 8b63f95..9f93731 100644
--- a/arch/risc-v/include/csr.h
+++ b/arch/risc-v/include/csr.h
@@ -311,10 +311,13 @@
 
 /* In mstatus register */
 
-#define MSTATUS_MIE   (0x1 << 3)  /* Machine Interrupt Enable */
-#define MSTATUS_MPIE  (0x1 << 7)  /* Machine Previous Interrupt Enable */
-#define MSTATUS_MPPM  (0x3 << 11) /* Machine Previous Privilege (m-mode) */
-#define MSTATUS_FS    (0x3 << 13) /* Machine Floating-point Status */
+#define MSTATUS_MIE       (0x1 << 3)  /* Machine Interrupt Enable */
+#define MSTATUS_MPIE      (0x1 << 7)  /* Machine Previous Interrupt Enable */
+#define MSTATUS_MPPM      (0x3 << 11) /* Machine Previous Privilege (m-mode) */
+#define MSTATUS_FS        (0x3 << 13) /* Machine Floating-point Status */
+#define MSTATUS_FS_INIT   (0x1 << 13)
+#define MSTATUS_FS_CLEAN  (0x2 << 13)
+#define MSTATUS_FS_DIRTY  (0x3 << 13)
 
 /* In mie (machine interrupt enable) register */
 
diff --git a/arch/risc-v/src/bl602/Make.defs b/arch/risc-v/src/bl602/Make.defs
index f0e3547..a1a1d69 100644
--- a/arch/risc-v/src/bl602/Make.defs
+++ b/arch/risc-v/src/bl602/Make.defs
@@ -38,6 +38,10 @@ ifeq ($(CONFIG_STACK_COLORATION),y)
 CMN_CSRCS += riscv_checkstack.c
 endif
 
+ifeq ($(CONFIG_ARCH_FPU),y)
+CMN_ASRCS  += riscv_fpu.S
+endif
+
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
 CMN_CSRCS  += riscv_vfork.c
 endif
diff --git a/arch/risc-v/src/bl602/bl602_irq.c b/arch/risc-v/src/bl602/bl602_irq.c
index 8bacc6c..7c2cd37 100644
--- a/arch/risc-v/src/bl602/bl602_irq.c
+++ b/arch/risc-v/src/bl602/bl602_irq.c
@@ -184,7 +184,11 @@ uint32_t up_get_newintctx(void)
    * Also set machine previous interrupt enable
    */
 
+#ifdef CONFIG_ARCH_FPU
+  return (MSTATUS_FS_INIT | MSTATUS_MPPM | MSTATUS_MPIE);
+#else
   return (MSTATUS_MPPM | MSTATUS_MPIE);
+#endif
 }
 
 /****************************************************************************
diff --git a/arch/risc-v/src/bl602/bl602_irq_dispatch.c b/arch/risc-v/src/bl602/bl602_irq_dispatch.c
index ba6c0f7..1979343 100644
--- a/arch/risc-v/src/bl602/bl602_irq_dispatch.c
+++ b/arch/risc-v/src/bl602/bl602_irq_dispatch.c
@@ -90,8 +90,36 @@ void *bl602_dispatch_irq(uint32_t vector, uint32_t *regs)
 
   irq_dispatch(irq, regs);
 
+#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV)
+  /* Check for a context switch.  If a context switch occurred, then
+   * g_current_regs will have a different value than it did on entry.  If an
+   * interrupt level context switch has occurred, then restore the floating
+   * point state and the establish the correct address environment before
+   * returning from the interrupt.
+   */
+
+  if (regs != g_current_regs)
+    {
+#ifdef CONFIG_ARCH_FPU
+      /* Restore floating point registers */
+
+      up_restorefpu((uint32_t *)g_current_regs);
 #endif
 
+#ifdef CONFIG_ARCH_ADDRENV
+      /* Make sure that the address environment for the previously
+       * running task is closed down gracefully (data caches dump,
+       * MMU flushed) and set up the address environment for the new
+       * thread at the head of the ready-to-run list.
+       */
+
+      group_addrenv(NULL);
+#endif
+    }
+#endif /* CONFIG_ARCH_FPU || CONFIG_ARCH_ADDRENV */
+
+#endif /* CONFIG_SUPPRESS_INTERRUPTS */
+
   /* If a context switch occurred while processing the interrupt then
    * g_current_regs may have change value.  If we return any value different
    * from the input regs, then the lower level will know that a context
diff --git a/arch/risc-v/src/rv32im/riscv_copystate.c b/arch/risc-v/src/rv32im/riscv_copystate.c
index 66e734a..f5ac1c4 100644
--- a/arch/risc-v/src/rv32im/riscv_copystate.c
+++ b/arch/risc-v/src/rv32im/riscv_copystate.c
@@ -70,6 +70,10 @@ void up_copystate(uint32_t *dest, uint32_t *src)
 {
   int i;
 
+#ifdef CONFIG_ARCH_FPU
+  uint32_t *regs = dest;
+#endif
+
   /* In the RISC-V model, the state is copied from the stack to the TCB,
    * but only a reference is passed to get the state from the TCB.  So the
    * following check avoids copying the TCB save area onto itself:
@@ -77,13 +81,20 @@ void up_copystate(uint32_t *dest, uint32_t *src)
 
   if (src != dest)
     {
-      for (i = 0; i < XCPTCONTEXT_REGS; i++)
+      /* save integer registers first */
+
+      for (i = 0; i < INT_XCPT_REGS; i++)
         {
           *dest++ = *src++;
         }
 
+      /* Save the floating point registers: This will initialize the floating
+       * registers at indices INT_XCPT_REGS through (XCPTCONTEXT_REGS-1).
+       * Do this after saving REG_INT_CTX with the ORIGINAL context pointer.
+       */
+
 #ifdef CONFIG_ARCH_FPU
-      up_savefpu(dest);
+      up_savefpu(regs);
 #endif
     }
 }
diff --git a/boards/risc-v/bl602/bl602evb/configs/fpu/defconfig b/boards/risc-v/bl602/bl602evb/configs/fpu/defconfig
new file mode 100644
index 0000000..dd241f7
--- /dev/null
+++ b/boards/risc-v/bl602/bl602evb/configs/fpu/defconfig
@@ -0,0 +1,77 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_DISABLEBG is not set
+# CONFIG_NSH_DISABLE_LOSMART is not set
+# CONFIG_NSH_DISABLE_UNAME is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="bl602evb"
+CONFIG_ARCH_BOARD_BL602EVB=y
+CONFIG_ARCH_CHIP="bl602"
+CONFIG_ARCH_CHIP_BL602=y
+CONFIG_ARCH_INTERRUPTSTACK=8192
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BINFMT_DISABLE=y
+CONFIG_BL602_HAVE_UART0=y
+CONFIG_BL602_TIMER0=y
+CONFIG_BOARD_LOOPSPERMSEC=10000
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEFAULT_SMALL=y
+CONFIG_DEV_ZERO=y
+CONFIG_DISABLE_MQUEUE=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_EXAMPLES_HELLO_STACKSIZE=8192
+CONFIG_EXAMPLES_TIMER=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=8192
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_MAX_TASKS=8
+CONFIG_NFILE_DESCRIPTORS=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_CD=y
+CONFIG_NSH_DISABLE_CP=y
+CONFIG_NSH_DISABLE_IFUPDOWN=y
+CONFIG_NSH_DISABLE_MKDIR=y
+CONFIG_NSH_DISABLE_RM=y
+CONFIG_NSH_DISABLE_RMDIR=y
+CONFIG_NSH_DISABLE_UMOUNT=y
+CONFIG_NSH_FILEIOSIZE=64
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_PTHREAD_STACK_DEFAULT=8192
+CONFIG_RAM_SIZE=134217728
+CONFIG_RAM_START=0xc0800000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_RV32IM_CUSTOM_IRQ_SUPPORT=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=20
+CONFIG_START_MONTH=3
+CONFIG_START_YEAR=2020
+CONFIG_STDIO_DISABLE_BUFFERING=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TASK_NAME_SIZE=12
+CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=8192
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_TESTING_OSTEST_FPUSIZE=132
+CONFIG_TIMER=y
+CONFIG_TIMER_ARCH=y
+CONFIG_UART0_BAUD=2000000
+CONFIG_UART0_RXBUFSIZE=128
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_UART0_TXBUFSIZE=128
+CONFIG_USERMAIN_STACKSIZE=8192
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/risc-v/bl602/bl602evb/src/Makefile b/boards/risc-v/bl602/bl602evb/src/Makefile
index cc66326..463f81f 100644
--- a/boards/risc-v/bl602/bl602evb/src/Makefile
+++ b/boards/risc-v/bl602/bl602evb/src/Makefile
@@ -33,4 +33,8 @@ ifeq ($(CONFIG_DEV_GPIO),y)
 CSRCS += bl602_gpio.c
 endif
 
+ifeq ($(CONFIG_ARCH_FPU),y)
+CSRCS += bl602_ostest.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
diff --git a/arch/risc-v/src/bl602/bl602_irq_dispatch.c b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
similarity index 54%
copy from arch/risc-v/src/bl602/bl602_irq_dispatch.c
copy to boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
index ba6c0f7..1c54fcc 100644
--- a/arch/risc-v/src/bl602/bl602_irq_dispatch.c
+++ b/boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/risc-v/src/bl602/bl602_irq_dispatch.c
+ * boards/risc-v/bl602/bl602evb/src/bl602_ostest.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -25,81 +25,68 @@
 #include <nuttx/config.h>
 
 #include <stdint.h>
-#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <syscall.h>
 
 #include <nuttx/irq.h>
-#include <nuttx/arch.h>
-#include <nuttx/board.h>
-#include <arch/board/board.h>
 
-#include "riscv_arch.h"
-#include "riscv_internal.h"
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
 
-#include "chip.h"
+#undef HAVE_FPU
+#if defined(CONFIG_ARCH_FPU) && \
+    !defined(CONFIG_TESTING_OSTEST_FPUTESTDISABLE) && \
+    defined(CONFIG_TESTING_OSTEST_FPUSIZE) && \
+    defined(CONFIG_SCHED_WAITPID)
+#    define HAVE_FPU 1
+#endif
+
+#ifdef HAVE_FPU
+
+#if CONFIG_TESTING_OSTEST_FPUSIZE != (4 * FPU_XCPT_REGS)
+#  error "CONFIG_TESTING_OSTEST_FPUSIZE has the wrong size"
+#endif
 
 /****************************************************************************
- * Public Data
+ * Private Data
  ****************************************************************************/
 
-volatile uint32_t *g_current_regs;
+static uint32_t g_saveregs[XCPTCONTEXT_REGS];
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
-/****************************************************************************
- * bl602_dispatch_irq
- ****************************************************************************/
+/* Given an array of size CONFIG_TESTING_OSTEST_FPUSIZE, this function will
+ * return the current FPU registers.
+ */
 
-void *bl602_dispatch_irq(uint32_t vector, uint32_t *regs)
+void arch_getfpu(FAR uint32_t *fpusave)
 {
-  uint32_t  irq  = vector & 0x3ff; /* E24 [9:0] */
-  uint32_t *mepc = regs;
-
-  /* If current is interrupt */
-
-  if (vector & 0x80000000u)
-    {
-      irq += BL602_IRQ_ASYNC;
-    }
+  irqstate_t flags;
 
-  /* NOTE: In case of ecall, we need to adjust mepc in the context */
+  /* Take a snapshot of the thread context right now */
 
-  if (BL602_IRQ_ECALLM == irq)
-    {
-      *mepc += 4;
-    }
+  flags = enter_critical_section();
+  up_saveusercontext(g_saveregs);
 
-  /* Acknowledge the interrupt */
+  /* Return only the floating register values */
 
-  up_ack_irq(irq);
-
-#ifdef CONFIG_SUPPRESS_INTERRUPTS
-  PANIC();
-#else
-  /* Current regs non-zero indicates that we are processing an interrupt;
-   * g_current_regs is also used to manage interrupt level context switches.
-   *
-   * Nested interrupts are not supported
-   */
-
-  DEBUGASSERT(g_current_regs == NULL);
-  g_current_regs = regs;
-
-  /* Deliver the IRQ */
-
-  irq_dispatch(irq, regs);
-
-#endif
-
-  /* If a context switch occurred while processing the interrupt then
-   * g_current_regs may have change value.  If we return any value different
-   * from the input regs, then the lower level will know that a context
-   * switch occurred during interrupt processing.
-   */
+  memcpy(fpusave, &g_saveregs[INT_XCPT_REGS], (4*FPU_XCPT_REGS));
+  leave_critical_section(flags);
+}
 
-  regs           = (uint32_t *)g_current_regs;
-  g_current_regs = NULL;
+/* Given two arrays of size CONFIG_TESTING_OSTEST_FPUSIZE this function
+ * will compare them and return true if they are identical.
+ */
 
-  return regs;
+bool arch_cmpfpu(FAR const uint32_t *fpusave1, FAR const uint32_t *fpusave2)
+{
+  return memcmp(fpusave1, fpusave2, (4*FPU_XCPT_REGS)) == 0;
 }
+
+#endif /* HAVE_FPU */