You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/04/22 13:33:04 UTC

[incubator-nuttx] branch master updated: Added support to crashdump for rx65n on sbram

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

gnutt 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 3133290  Added support to crashdump for rx65n on sbram
3133290 is described below

commit 31332904dd10b7d0e8060e1a667f250888ec9aa4
Author: rajeshwaribhat <ra...@tataelxsi.co.in>
AuthorDate: Tue Apr 21 16:39:21 2020 +0530

    Added support to crashdump for rx65n on sbram
---
 arch/renesas/src/rx65n/Kconfig                     |  28 +
 arch/renesas/src/rx65n/Make.defs                   |   2 +-
 arch/renesas/src/rx65n/rx65n_definitions.h         |  14 +-
 arch/renesas/src/rx65n/rx65n_dumpstate.c           |  45 +-
 arch/renesas/src/rx65n/rx65n_sbram.c               | 806 +++++++++++++++++++++
 arch/renesas/src/rx65n/rx65n_sbram.h               | 145 ++++
 boards/renesas/rx65n/rx65n-grrose/src/Makefile     |   2 +-
 .../renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c |   3 +-
 .../renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c |   9 +-
 .../src/{rx65n_appinit.c => rx65n_grrose.h}        |  70 +-
 .../renesas/rx65n/rx65n-grrose/src/rx65n_sbram.c   | 490 +++++++++++++
 boards/renesas/rx65n/rx65n-rsk2mb/src/Makefile     |   2 +-
 .../renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c |   7 +
 .../src/rx65n_rsk2mb.h}                            |  70 +-
 .../renesas/rx65n/rx65n-rsk2mb/src/rx65n_sbram.c   | 487 +++++++++++++
 15 files changed, 2064 insertions(+), 116 deletions(-)

diff --git a/arch/renesas/src/rx65n/Kconfig b/arch/renesas/src/rx65n/Kconfig
index 676ca49..7d211a9 100644
--- a/arch/renesas/src/rx65n/Kconfig
+++ b/arch/renesas/src/rx65n/Kconfig
@@ -146,6 +146,11 @@ config RX65N_CMT0
 	bool "CMT0"
 	default y
 
+config RX65N_CMT1
+	bool "CMT1"
+	default n
+	depends on BOARD_CRASHDUMP && RX65N_SBRAM && RX65N_SAVE_CRASHDUMP
+
 config RX65N_CMT2
 	bool "CMT2"
 	default y
@@ -162,6 +167,15 @@ config RX65N_IRQ_GROUP
 	bool "IRQ_GROUP"
 	default y
 
+config RX65N_SBRAM
+	bool "SBRAM"
+	default n
+	depends on BOARD_CRASHDUMP
+
+config RX65N_SAVE_CRASHDUMP
+	bool "SBRAM Save Crashdump"
+	depends on RX65N_SBRAM
+
 config RX65N_EMAC
 	bool
 	default n
@@ -272,6 +286,11 @@ config RX65N_CMT0
 	bool "CMT0"
 	default y
 
+config RX65N_CMT1
+	bool "CMT1"
+	default n
+	depends on BOARD_CRASHDUMP && RX65N_SBRAM && RX65N_SAVE_CRASHDUMP
+
 config RX65N_CMT2
 	bool "CMT2"
 	default y
@@ -288,6 +307,15 @@ config RX65N_IRQ_GROUP
 	bool "IRQ_GROUP"
 	default y
 
+config RX65N_SBRAM
+	bool "SBRAM"
+	default n
+	depends on BOARD_CRASHDUMP
+
+config RX65N_SAVE_CRASHDUMP
+	bool "SBRAM Save Crashdump"
+	depends on RX65N_SBRAM
+
 config RX65N_EMAC
 	bool
 	default n
diff --git a/arch/renesas/src/rx65n/Make.defs b/arch/renesas/src/rx65n/Make.defs
index 07b2673..31cc582 100644
--- a/arch/renesas/src/rx65n/Make.defs
+++ b/arch/renesas/src/rx65n/Make.defs
@@ -47,7 +47,7 @@ CHIP_CSRCS = rx65n_lowputc.c rx65n_serial.c rx65n_copystate.c  rx65n_irq.c
 CHIP_CSRCS += rx65n_schedulesigaction.c rx65n_sigdeliver.c rx65n_initialstate.c
 CHIP_CSRCS += rx65n_hardware_setup.c rx65n_icu.c rx65n_port.c rx65n_sci.c
 CHIP_CSRCS += rx65n_cgc.c rx65n_dumpstate.c rx65n_vector_table.c
-CHIP_CSRCS += rx65n_timerisr.c
+CHIP_CSRCS += rx65n_timerisr.c rx65n_sbram.c
 
 ifeq ($(CONFIG_RX65N_EMAC),y)
 CHIP_CSRCS += rx65n_eth.c rx65n_cmtw0.c
diff --git a/arch/renesas/src/rx65n/rx65n_definitions.h b/arch/renesas/src/rx65n/rx65n_definitions.h
index 5a9a2e0..ee6fa5f 100644
--- a/arch/renesas/src/rx65n/rx65n_definitions.h
+++ b/arch/renesas/src/rx65n/rx65n_definitions.h
@@ -92,7 +92,7 @@
 
 #define RX_SCISCR_SXSIN1   (0x02)
 
-/*   External clock, SCK pin used for clock input */
+/* External clock, SCK pin used for clock input */
 
 #define RX_SCISCR_SXSIN2   (0x03)
 
@@ -174,10 +174,10 @@
 
 #define RX65N_CMT_CMCR_DEFAULT          (0x0080)
 #define RX65N_CMT_CMCR_CMIE_ENABLE      (0x0040)
-#define RX65N_CMT_MSTPCRA_STOP          (0x00008000)    /*Release unit0(CMT0 and CMT1) from module stop state*/
-#define RX65N_CMT_UNIT1_MSTPCRA_STOP    (0x00004000)    /*Release unit1(CMT2 and CMT3) from module stop state*/
-#define RX65N_CMTW_UNIT1_MSTPCRA_STOP   (0x00000001)    /*Release CMTW unit1 from module stop state*/
-#define RX65N_CMTW_UNIT0_MSTPCRA_STOP   (0x00000002)    /*Release CMTW unit0 from module stop state*/
+#define RX65N_CMT_MSTPCRA_STOP          (0x00008000)    /* Release unit0(CMT0 and CMT1) from module stop state */
+#define RX65N_CMT_UNIT1_MSTPCRA_STOP    (0x00004000)    /* Release unit1(CMT2 and CMT3) from module stop state */
+#define RX65N_CMTW_UNIT1_MSTPCRA_STOP   (0x00000001)    /* Release CMTW unit1 from module stop state */
+#define RX65N_CMTW_UNIT0_MSTPCRA_STOP   (0x00000002)    /* Release CMTW unit0 from module stop state */
 #define RX65N_CMTCMSTR0_STR0            (0x0001)        /* Bit 0: TCNT0 is counting */
 #define RX65N_CMTCMSTR0_STR1            (0x0002)        /* Bit 1: TCNT1 is counting */
 #define RX65N_CMTCMSTR1_STR2            (0x0001)        /* Bit 0: TCNT0 is counting */
@@ -537,6 +537,10 @@
 #define RTC_RCR2_HR24         (0x40)
 #define RTC_PERIODIC_INTERRUPT_2_SEC (0xf)
 
+/* StandBy RAM Address */
+
+#define RX65N_SBRAM_BASE  0x000a4000
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
diff --git a/arch/renesas/src/rx65n/rx65n_dumpstate.c b/arch/renesas/src/rx65n/rx65n_dumpstate.c
index 20c4556..e72cdd4 100644
--- a/arch/renesas/src/rx65n/rx65n_dumpstate.c
+++ b/arch/renesas/src/rx65n/rx65n_dumpstate.c
@@ -1,35 +1,20 @@
 /****************************************************************************
  * arch/renesas/src/rx65n/rx65n_dumpstate.c
  *
- *   Copyright (C) 2008-2019 Gregory Nutt. All rights reserved.
- *   Author: Anjana <an...@tataelxsi.co.in>
+ * 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
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *   http://www.apache.org/licenses/LICENSE-2.0
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  ****************************************************************************/
 
@@ -64,10 +49,10 @@ static uint32_t s_last_regs[XCPTCONTEXT_REGS];
  ****************************************************************************/
 
 /****************************************************************************
- * Name: rx65n_getsp
+ * Name: up_getsp
  ****************************************************************************/
 
-static inline uint16_t rx65n_getsp(void)
+uint16_t up_getsp(void)
 {
   uint16_t sp;
 
@@ -156,7 +141,7 @@ static inline void rx65n_registerdump(void)
 void up_dumpstate(void)
 {
   struct tcb_s *rtcb = running_task();
-  uint32_t sp = rx65n_getsp();
+  uint32_t sp = up_getsp();
   uint32_t ustackbase;
   uint32_t ustacksize;
 #if CONFIG_ARCH_INTERRUPTSTACK > 3
diff --git a/arch/renesas/src/rx65n/rx65n_sbram.c b/arch/renesas/src/rx65n/rx65n_sbram.c
new file mode 100644
index 0000000..1e3ec89
--- /dev/null
+++ b/arch/renesas/src/rx65n/rx65n_sbram.c
@@ -0,0 +1,806 @@
+/****************************************************************************
+ * arch/renesas/src/rx65n/rx65n_sbram.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* This will driver create a set of files in the RX65N's Battery backed up
+ * SRAM. That can be used to store data retained across power cycles.
+ *
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <poll.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <nuttx/fs/fs.h>
+
+#include <crc32.h>
+
+#include "rx65n_sbram.h"
+#include "chip.h"
+
+#ifdef CONFIG_RX65N_SBRAM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MAX_OPENCNT           (255) /* Limit of uint8_t */
+
+#ifndef CONFIG_DEBUG_INFO
+#  undef CONFIG_SBRAM_DEBUG
+#endif
+
+#if defined(CONFIG_SBRAM_DEBUG)
+#  define SBRAM_DEBUG_READ() rx65n_sbram_rd()
+#  define SBRAM_DUMP(p,s)    rx65n_sbram_dump(p,s)
+#else
+#  define SBRAM_DEBUG_READ()
+#  define SBRAM_DUMP(p,s)
+#endif
+
+#define SBRAM_HEADER_SIZE    (sizeof(struct sbramfh_s))
+#define SBRAM_CRCED_OFFSET   (sizeof(((struct sbramfh_s *)0)->crc))
+#define SBRAM_CRCED_SIZE(l)  (SBRAM_HEADER_SIZE-(SBRAM_CRCED_OFFSET)+(l))
+#define SBRAM_ALIGNMENT      (sizeof(((struct sbramfh_s *)0)->crc))
+#define SBRAM_ALIGNMENT_MASK (SBRAM_ALIGNMENT-1)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* File Header */
+
+struct sbramfh_s
+{
+  uint32_t crc;                /* CRC calculated over data and this struct
+                                * starting at fileno */
+  uint8_t fileno;              /* The minor number */
+  uint8_t dirty;               /* Data has been written to the file */
+  uint16_t len;                /* Total Bytes in this file */
+  struct timespec lastwrite;   /* Last write time */
+  uint8_t  data[];             /* Data in the file */
+};
+
+struct rx65n_sbram_s
+{
+  sem_t    exclsem;            /* For atomic accesses to this structure */
+  uint8_t  refs;               /* Number of references */
+  FAR struct sbramfh_s *bbf;   /* File in bbram */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int     rx65n_sbram_open(FAR struct file *filep);
+static int     rx65n_sbram_close(FAR struct file *filep);
+static off_t   rx65n_sbram_seek(FAR struct file *filep, off_t offset,
+                 int whence);
+static ssize_t rx65n_sbram_read(FAR struct file *filep, FAR char *buffer,
+                 size_t len);
+static ssize_t rx65n_sbram_write(FAR struct file *filep,
+                 FAR const char *buffer, size_t len);
+static int rx65n_sbram_ioctl(FAR struct file *filep, int cmd,
+                 unsigned long arg);
+static int     rx65n_sbram_poll(FAR struct file *filep,
+                                FAR struct pollfd *fds,
+                                                                 bool setup);
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+static int     rx65n_sbram_unlink(FAR struct inode *inode);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if defined(CONFIG_SBRAM_DEBUG)
+static uint8_t debug[RX65N_SBRAM_SIZE];
+#endif
+
+static const struct file_operations rx65n_sbram_fops =
+{
+  .open   = rx65n_sbram_open,
+  .close  = rx65n_sbram_close,
+  .read   = rx65n_sbram_read,
+  .write  = rx65n_sbram_write,
+  .seek   = rx65n_sbram_seek,
+  .ioctl  = rx65n_sbram_ioctl,
+  .poll   = rx65n_sbram_poll,
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  .unlink = rx65n_sbram_unlink,
+#endif
+};
+
+static struct rx65n_sbram_s g_sbram[CONFIG_RX65N_SBRAM_FILES];
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rx65n_sbram_rd
+ ****************************************************************************/
+
+#if defined(CONFIG_SBRAM_DEBUG)
+static void rx65n_sbram_rd(void)
+{
+  memcpy(&debug, (uint8_t *)RX65N_SBRAM_BASE, sizeof debug);
+}
+#endif
+
+/****************************************************************************
+ * Name: rx65n_sbram_rd
+ ****************************************************************************/
+
+#if defined(CONFIG_SBRAM_DEBUG)
+static void rx65n_sbram_dump(FAR struct sbramfh_s *bbf, char *op)
+{
+  SBRAM_DEBUG_READ();
+  _info("%s:\n", op);
+  _info(" File Address:0x%8x\n", bbf);
+  _info("  crc:0x%8x\n", bbf->crc);
+  _info("  fileno:%d\n", (int) bbf->fileno);
+  _info("  dirty:%d\n", (int) bbf->dirty);
+  _info("  length:%d\n", (int) bbf->len);
+  _info("  time:%ld:%ld\n", bbf->lastwrite.tv_sec, bbf->lastwrite.tv_nsec);
+  _info("  data: 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x\n",
+  bbf->data[0], bbf->data[1], bbf->data[2], bbf->data[3], bbf->data[4]);
+}
+#endif
+
+/****************************************************************************
+ * Name: rx65n_sbram_semgive
+ ****************************************************************************/
+
+static void rx65n_sbram_semgive(FAR struct rx65n_sbram_s *priv)
+{
+  nxsem_post(&priv->exclsem);
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_semtake
+ *
+ * Description:
+ *   Take a semaphore handling any exceptional conditions
+ *
+ * Input Parameters:
+ *   priv - A reference to the CAN peripheral state
+ *
+ * Returned Value:
+ *  None
+ *
+ ****************************************************************************/
+
+static void rx65n_sbram_semtake(FAR struct rx65n_sbram_s *priv)
+{
+  int ret;
+
+  /* Wait until we successfully get the semaphore.  EINTR is the only
+   * expected 'failure' (meaning that the wait for the semaphore was
+   * interrupted by a signal.
+   */
+
+  do
+    {
+      ret = nxsem_wait(&priv->exclsem);
+      DEBUGASSERT(ret == OK || ret == -EINTR);
+    }
+  while (ret == -EINTR);
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_crc
+ *
+ * Description:
+ *   Calculates the CRC of the block
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static uint32_t rx65n_sbram_crc(FAR struct sbramfh_s *pf)
+{
+  return crc32((uint8_t *)pf + SBRAM_CRCED_OFFSET,
+    SBRAM_CRCED_SIZE(pf->len));
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_open
+ *
+ * Description: Open the device
+ *
+ ****************************************************************************/
+
+static int rx65n_sbram_open(FAR struct file *filep)
+{
+  FAR struct inode *inode = fil
+  ep->f_inode;
+  FAR struct rx65n_sbram_s *bbr;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  /* Increment the reference count */
+
+  rx65n_sbram_semtake(bbr);
+  if (bbr->refs == MAX_OPENCNT)
+    {
+      return -EMFILE;
+    }
+  else
+    {
+      bbr->refs++;
+    }
+
+  rx65n_sbram_semgive(bbr);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_internal_close
+ *
+ * Description:
+ *    Close SBRAM entry; Recalculate the time and crc
+ *
+ ****************************************************************************/
+
+static int rx65n_sbram_internal_close(FAR struct sbramfh_s *bbf)
+{
+  bbf->dirty = 0;
+  (void)clock_gettime(CLOCK_REALTIME, &bbf->lastwrite);
+  bbf->crc = rx65n_sbram_crc(bbf);
+
+  SBRAM_DUMP(bbf, "close done");
+  return bbf->len;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_close
+ *
+ * Description: close the device
+ *
+ ****************************************************************************/
+
+static int rx65n_sbram_close(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rx65n_sbram_s *bbr;
+  int ret = OK;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  rx65n_sbram_semtake(bbr);
+
+  SBRAM_DUMP(bbr->bbf, "close");
+
+  if (bbr->refs == 0)
+    {
+      ret = -EIO;
+    }
+  else
+    {
+      bbr->refs--;
+
+      if (bbr->refs == 0)
+        {
+          if (bbr->bbf->dirty)
+            {
+              /* Recalculate the time and crc */
+
+              rx65n_sbram_internal_close(bbr->bbf);
+            }
+        }
+    }
+
+  rx65n_sbram_semgive(bbr);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_seek
+ ****************************************************************************/
+
+static off_t rx65n_sbram_seek(FAR struct file *filep, off_t offset,
+                               int whence)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rx65n_sbram_s *bbr;
+  off_t newpos;
+  int ret;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  rx65n_sbram_semtake(bbr);
+
+  /* Determine the new, requested file position */
+
+  switch (whence)
+    {
+    case SEEK_CUR:
+      newpos = filep->f_pos + offset;
+      break;
+
+    case SEEK_SET:
+      newpos = offset;
+      break;
+
+    case SEEK_END:
+      newpos = bbr->bbf->len + offset;
+      break;
+
+    default:
+
+      /* Return EINVAL if the whence argument is invalid */
+
+      rx65n_sbram_semgive(bbr);
+      return -EINVAL;
+    }
+
+  /* Opengroup.org:
+   *
+   *  "The lseek() function shall allow the file offset to be set
+   *   beyond the end of the existing data in the file. If data is
+   *   later written at this point,
+   *   subsequent reads of data in the gap shall return bytes with the value
+   *   0 until data is actually written into the gap."
+   *
+   * We can conform to the first part, but not the second.
+   * But return EINVAL if
+   *
+   *  "...the resulting file offset would be negative for a regular
+   *  file, block
+   *   special file, or directory."
+   */
+
+  if (newpos >= 0)
+    {
+      filep->f_pos = newpos;
+      ret = newpos;
+    }
+  else
+    {
+      ret = -EINVAL;
+    }
+
+  rx65n_sbram_semgive(bbr);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_read
+ ****************************************************************************/
+
+static ssize_t rx65n_sbram_read(FAR struct file *filep, FAR char *buffer,
+                                 size_t len)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rx65n_sbram_s *bbr;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  rx65n_sbram_semtake(bbr);
+
+  /* Trim len if read would go beyond end of device */
+
+  if ((filep->f_pos + len) > bbr->bbf->len)
+    {
+      len = bbr->bbf->len - filep->f_pos;
+    }
+
+  memcpy(buffer, &bbr->bbf->data[filep->f_pos], len);
+  filep->f_pos += len;
+  rx65n_sbram_semgive(bbr);
+  return len;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_internal_write
+ ****************************************************************************/
+
+static ssize_t rx65n_sbram_internal_write(FAR struct sbramfh_s *bbf,
+                                           FAR const char *buffer,
+                                           off_t offset, size_t len)
+{
+  bbf->dirty = 1;
+  memcpy(&bbf->data[offset], buffer, len);
+  return len;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_write
+ ****************************************************************************/
+
+static ssize_t rx65n_sbram_write(FAR struct file *filep,
+                                 FAR const char *buffer,
+                                  size_t len)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rx65n_sbram_s *bbr;
+  int ret = -EFBIG;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  /* Forbid writes past the end of the device */
+
+  if (filep->f_pos <  bbr->bbf->len)
+    {
+      /* Clamp len to avoid crossing the end of the memory */
+
+      if ((filep->f_pos + len) > bbr->bbf->len)
+        {
+          len = bbr->bbf->len - filep->f_pos;
+        }
+
+      ret = len; /* save number of bytes written */
+
+      rx65n_sbram_semtake(bbr);
+      SBRAM_DUMP(bbr->bbf, "write");
+      rx65n_sbram_internal_write(bbr->bbf, buffer, filep->f_pos, len);
+      filep->f_pos += len;
+      SBRAM_DUMP(bbr->bbf, "write done");
+      rx65n_sbram_semgive(bbr);
+    }
+
+  SBRAM_DEBUG_READ();
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_poll
+ ****************************************************************************/
+
+static int rx65n_sbram_poll(FAR struct file *filep, FAR struct pollfd *fds,
+                             bool setup)
+{
+  if (setup)
+    {
+      fds->revents |= (fds->events & (POLLIN | POLLOUT));
+      if (fds->revents != 0)
+        {
+          nxsem_post(fds->sem);
+        }
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_ioctl
+ *
+ * Description: Return device geometry
+ *
+ ****************************************************************************/
+
+static int rx65n_sbram_ioctl(FAR struct file *filep, int cmd,
+                              unsigned long arg)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rx65n_sbram_s *bbr;
+  int ret = -ENOTTY;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  if (cmd == RX65N_SBRAM_GETDESC_IOCTL)
+    {
+      FAR struct sbramd_s *bbrr = (FAR struct sbramd_s *)((uintptr_t)arg);
+
+      rx65n_sbram_semtake(bbr);
+      if (!bbrr)
+        {
+          ret = -EINVAL;
+        }
+      else
+        {
+          bbrr->fileno = bbr->bbf->fileno;
+          bbrr->lastwrite = bbr->bbf->lastwrite;
+          bbrr->len = bbr->bbf->len;
+          bbrr->flags = ((bbr->bbf->crc == rx65n_sbram_crc(bbr->bbf))
+                          ? SBRAM_CRC_VALID : 0);
+          bbrr->flags |= ((bbr->bbf->dirty) ? SBRAM_DIRTY : 0);
+          ret = OK;
+        }
+
+      rx65n_sbram_semgive(bbr);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: rx65n_sbram_unlink
+ *
+ * Description:
+ *  This function will remove the remove the file from the file system
+ *  it will zero the contents and time stamp. It will leave the fileno
+ *  and pointer to the SBRAM intact.
+ *  It should be called called on the file used for the crash dump
+ *  to remove it from visibility in the file system after it is created or
+ *  read thus arming it.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+static int rx65n_sbram_unlink(FAR struct inode *inode)
+{
+  FAR struct rx65n_sbram_s *bbr;
+
+  DEBUGASSERT(inode && inode->i_private);
+  bbr = (FAR struct rx65n_sbram_s *)inode->i_private;
+
+  rx65n_sbram_semtake(bbr);
+  memset(bbr->bbf->data, 0, bbr->bbf->len);
+  bbr->bbf->lastwrite.tv_nsec = 0;
+  bbr->bbf->lastwrite.tv_sec = 0;
+  bbr->bbf->crc = rx65n_sbram_crc(bbr->bbf);
+  bbr->refs  = 0;
+  rx65n_sbram_semgive(bbr);
+  nxsem_destroy(&bbr->exclsem);
+  return 0;
+}
+#endif
+
+/****************************************************************************
+ * Name: rx65n_sbram_probe
+ *
+ * Description: Based on the number of files defined and their sizes
+ * Initializes the base pointers to the file entries.
+ *
+ ****************************************************************************/
+
+static int rx65n_sbram_probe(int *ent, struct rx65n_sbram_s pdev[])
+{
+  int i;
+  int avail = RX65N_SBRAM_SIZE;
+  int alloc;
+  int size;
+  int ret = -EFBIG;
+  struct sbramfh_s *pf = (struct sbramfh_s *) RX65N_SBRAM_BASE;
+
+  for (i = 0; (i < CONFIG_RX65N_SBRAM_FILES) && ent[i] && (avail > 0); i++)
+    {
+      /* Validate the actual allocations against what is in the SBRAM */
+
+      size = ent[i];
+
+      /* Use all that is left */
+
+      if (size == -1)
+        {
+          size = avail - (SBRAM_HEADER_SIZE + SBRAM_ALIGNMENT_MASK);
+        }
+
+      /* Add in header size and keep aligned */
+
+      alloc = size + SBRAM_HEADER_SIZE + SBRAM_ALIGNMENT_MASK;
+      alloc &= ~(SBRAM_ALIGNMENT_MASK);
+
+      /* Does it fit? */
+
+      if (alloc <= avail)
+        {
+          ret = i + 1;
+          SBRAM_DUMP(pf, "probe");
+          if (pf->len != size ||
+              pf->fileno != i ||
+              pf->crc != rx65n_sbram_crc(pf))
+            {
+              /* Not Valid so wipe the file in SBRAM */
+
+              memset((uint8_t *)pf, 0, alloc);
+              pf->fileno = i;
+              pf->len = size;
+              pf->crc = rx65n_sbram_crc(pf);
+              SBRAM_DUMP(pf, "probe reset");
+            }
+
+          pdev[i].bbf = pf;
+          pf = (struct sbramfh_s *)((uint8_t *)pf + alloc);
+          nxsem_init(&g_sbram[i].exclsem, 0, 1);
+        }
+
+      avail -= alloc;
+    }
+
+  SBRAM_DEBUG_READ();
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: rx65n_sbraminitialize
+ *
+ * Description:
+ *   Initialize the Battery Backed up SRAM driver.
+ *
+ * Input Parameters:
+ *   devpath - the path to instantiate the files.
+ *   sizes   - Pointer to a any array of file sizes to create
+ *             the last entry should be 0
+ *             A size of -1 will use all the remaining spaces
+ *
+ * If the length of sizes is greater then CONFIG_RX65N_SBRAM_FILES
+ * CONFIG_RX65N_SBRAM_FILES will be returned.
+ *
+ * Returned Value:
+ *   Number of files created on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+int rx65n_sbraminitialize(char *devpath, int *sizes)
+{
+  int i;
+  int fcnt;
+  char path[32];
+  char devname[32];
+
+  int ret = OK;
+
+  if (devpath == NULL)
+    {
+      return -EINVAL;
+    }
+
+  i = strlen(devpath);
+  if (i == 0 || i > sizeof(path) + 3)
+    {
+      return -EINVAL;
+    }
+
+  memset(g_sbram, 0, sizeof(g_sbram));
+
+  /* Clocking for the PWR block must be provided.  However, this is done
+   * unconditionally in rx65nf40xxx_rcc.c on power up.  This done
+   * unconditionally because the PWR block is also needed to set the
+   * internal voltage regulator for maximum performance.
+   */
+
+  /* Enable backup SRAM clock is done in rcc_enableahb1() when
+   * CONFIG_RX65N_SBRAM is defined.
+   */
+
+  /* Allow Access */
+
+  fcnt = rx65n_sbram_probe(sizes, g_sbram);
+
+  strncpy(path, devpath, sizeof(path));
+  strcat(path, "%d");
+
+  for (i = 0; i < fcnt && ret >= OK; i++)
+    {
+      snprintf(devname, sizeof(devname), path, i);
+      ret = register_driver(devname, &rx65n_sbram_fops, 0666, &g_sbram[i]);
+    }
+
+  /* Disallow Access */
+
+  return ret < OK ? ret : fcnt;
+}
+
+/****************************************************************************
+ * Function: rx65n_sbram_savepanic
+ *
+ * Description:
+ *   Saves the panic context in a previously allocated SBRAM file
+ *
+ * Input Parameters:
+ *   fileno  - the value returned by the ioctl RX65N_SBRAM_GETDESC_IOCTL
+ *   context - Pointer to a any array of bytes to save
+ *   length  - The length of the data pointed to byt context
+ *
+ * Returned Value:
+ *   Length saved or negated errno.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+int rx65n_sbram_savepanic(int fileno, uint8_t *context, int length)
+{
+  FAR struct sbramfh_s *bbf;
+  int fill;
+  int ret = -ENOSPC;
+
+  /* On a bad day we could panic while panicking, (and we debug assert)
+   * this is a potential feeble attempt at only writing the first
+   * panic's context to the file
+   */
+
+  static bool once = false;
+
+  if (!once)
+    {
+      once = true;
+
+      DEBUGASSERT(fileno > 0 && fileno < CONFIG_RX65N_SBRAM_FILES);
+
+      bbf = g_sbram[fileno].bbf;
+
+      DEBUGASSERT(bbf);
+
+      /* If the g_sbram has been nulled out we return ENXIO.
+       *
+       * As once ensures we will keep the first dump. Checking the time for
+       * 0 protects from over writing a previous crash dump that has not
+       * been saved to long term storage and erased.  The dreaded reboot
+       * loop.
+       */
+
+      if (!bbf)
+        {
+          ret = -ENXIO;
+        }
+      else if ((bbf->lastwrite.tv_sec == 0 && bbf->lastwrite.tv_nsec == 0))
+        {
+          /* Clamp length if too big  */
+
+          if (length > bbf->len)
+            {
+              length = bbf->len;
+            }
+
+          rx65n_sbram_internal_write(bbf, (char *) context, 0, length);
+
+          /* Fill with 0 if data is less then file size */
+
+          fill = (int) bbf->len - length;
+
+          if (fill > 0)
+            {
+              memset(&bbf->data[length], 0, fill);
+            }
+
+          /* Seal the file */
+
+          rx65n_sbram_internal_close(bbf);
+
+          ret = length;
+        }
+    }
+
+  return ret;
+}
+#endif
+
+#endif /* CONFIG_SBRAM_DRIVER */
diff --git a/arch/renesas/src/rx65n/rx65n_sbram.h b/arch/renesas/src/rx65n/rx65n_sbram.h
new file mode 100644
index 0000000..f1487ee
--- /dev/null
+++ b/arch/renesas/src/rx65n/rx65n_sbram.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+ * arch/renesas/src/rx65n/rx65n_sbram.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RENESAS_SRC_RX65N_RX65N_SBSRAM_H
+#define __ARCH_RENESAS_SRC_RX65N_RX65N_SBSRAM_H
+
+/****************************************************************************
+ * The purpose of this driver is to add battery backup file to the file
+ * system. There can be CONFIG_RX65N_BBRSRAM_COUNT files defined.
+ * These files are of fixed size up to the maximum of the backing 4K SRAM.
+ *
+ * If CONFIG_SAVE_CRASHDUMP is defined The driver also supports a feature
+ * to save the context of a PANIC in one of these files.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/fs/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  define RX65N_SBRAM_SIZE 8192
+
+#if !defined(CONFIG_RX65N_SBRAM_FILES)
+#  define CONFIG_RX65N_SBRAM_FILES 4
+#endif
+
+/* REVISIT: What guarantees that RX65N_SBRAM_GETDESC_IOCTL has a unique
+ * value among all over _DIOC() values?
+ */
+
+#define RX65N_SBRAM_GETDESC_IOCTL _DIOC(0x0010) /* Returns a sbramd_s */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+enum sbramdf_e
+{
+  SBRAM_CRC_VALID = 1,        /* The crc is valid */
+  SBRAM_DIRTY     = 2,        /* The file was closed */
+};
+
+struct sbramd_s
+{
+  uint8_t flags;               /* The crc is valid and the file was closed */
+  uint8_t fileno;              /* The minor number */
+  uint16_t len;                /* Total Bytes in this file */
+  struct timespec lastwrite;   /* Last write time */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#  define EXTERN extern "C"
+extern "C"
+{
+#else
+#  define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: rx65n_sbraminitialize
+ *
+ * Description:
+ *   Initialize the Battery Backed up SRAM driver.
+ *
+ * Input Parameters:
+ *   devpath - the path to instantiate the files.
+ *   sizes   - Pointer to a any array of file sizes to create
+ *             the last entry should be 0
+ *             A size of -1 will use all the remaining spaces
+ *
+ * If the length of sizes is greater then CONFIG_RX65N_SBRAM_FILES
+ * CONFIG_RX65N_SBRAM_FILES will be returned.
+ *
+ * Returned Value:
+ *   Number of files created on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+int rx65n_sbraminitialize(char *devpath, int *sizes);
+
+/****************************************************************************
+* Function: rx65n_sbram_savepanic
+*
+* Description:
+*   Saves the panic context in a previously allocated SBRAM file
+*
+* Parameters:
+*   fileno  - the value returned by the ioctl RX65N_SBRAM_GETDESC_IOCTL
+*   context - Pointer to a any array of bytes to save
+*   length  - The length of the data pointed to byt context
+*
+* Returned Value:
+*   Length saved or negated errno.
+*
+* Assumptions:
+*
+*****************************************************************************/
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+int rx65n_sbram_savepanic(int fileno, uint8_t *context, int length);
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_RX65N_RX65N_SBRAM_H */
diff --git a/boards/renesas/rx65n/rx65n-grrose/src/Makefile b/boards/renesas/rx65n/rx65n-grrose/src/Makefile
index 645bbe7..3cf1dfb 100644
--- a/boards/renesas/rx65n/rx65n-grrose/src/Makefile
+++ b/boards/renesas/rx65n/rx65n-grrose/src/Makefile
@@ -26,7 +26,7 @@ CFLAGS += -I=$(ARCH_SRCDIR)/chip
 
 ASRCS =
 AOBJS = $(ASRCS:.asm=$(OBJEXT))
-CSRCS = rx65n_appinit.c rx65n_bringup.c
+CSRCS = rx65n_appinit.c rx65n_bringup.c rx65n_sbram.c
 COBJS = $(CSRCS:.c=$(OBJEXT))
 
 SRCS = $(ASRCS) $(CSRCS)
diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
index 20e093e..4feccfe 100644
--- a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
+++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
+ * boards/renesas/rx65n/rx65n-grrose/src/rx65n.appinit.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -28,6 +28,7 @@
 #include <stdint.h>
 
 #include <nuttx/board.h>
+#include "rx65n_grrose.h"
 
 #ifdef CONFIG_LIB_BOARDCTL
 
diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c
index 043f62a..c83b348 100644
--- a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c
+++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/renesas/rx65n/rx65n-grrose/src/rx65n_bringup.c
+ * boards/renesas/rx65n/rx65n-grrose/src/rx65n.bringup.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -34,6 +34,7 @@
 
 #include <nuttx/board.h>
 
+#include "rx65n_grrose.h"
 #include <rx65n_definitions.h>
 #ifdef CONFIG_LIB_BOARDCTL
 
@@ -123,6 +124,12 @@ int rx65n_bringup(void)
     }
 
 #endif
+
+#ifdef CONFIG_RX65N_SBRAM
+  /* Initialize battery-backed RAM */
+
+  (void)rx65n_sbram_int();
+#endif
   return OK;
 }
 
diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h
similarity index 50%
copy from boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
copy to boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h
index 20e093e..eb55044 100644
--- a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
+++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
+ * boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,64 +18,58 @@
  *
  ****************************************************************************/
 
+#ifndef __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H
+#define __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
-
-#include <sys/types.h>
+#include <nuttx/compiler.h>
 #include <stdint.h>
 
-#include <nuttx/board.h>
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
 
-#ifdef CONFIG_LIB_BOARDCTL
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
 
 /****************************************************************************
- * Public Functions
+ * Public data
  ****************************************************************************/
 
+#ifndef __ASSEMBLY__
+
 /****************************************************************************
- * Name: board_app_initialize
+ * Name: rx65n_bringup
  *
  * Description:
- *   Perform application specific initialization.  This function is never
- *   called directly from application code, but only indirectly via the
- *   (non-standard) boardctl() interface using the command BOARDIOC_INIT.
- *
- *   CONFIG_LIB_BOARDCTL=y :
- *     Called from the NSH library
+ *   Perform architecture-specific initialization
  *
- *   CONFIG_BOARD_LATE_INITIALIZE=y, CONFIG_NSH_LIBRARY=y, &&
- *   CONFIG_LIB_BOARDCTL=n :
+ *   CONFIG_BOARD_LATE_INITIALIZE=y :
  *     Called from board_late_initialize().
  *
- * Input Parameters:
- *   arg - The boardctl() argument is passed to the board_app_initialize()
- *         implementation without modification.  The argument has no
- *         meaning to NuttX; the meaning of the argument is a contract
- *         between the board-specific initialization logic and the
- *         matching application logic.  The value cold be such things as a
- *         mode enumeration value, a set of DIP switch switch settings, a
- *         pointer to configuration data read from a file or serial FLASH,
- *         or whatever you would like to do with it.  Every implementation
- *         should accept zero/NULL as a default configuration.
- *
- * Returned Value:
- *   Zero (OK) is returned on success; a negated errno value is returned on
- *   any failure to indicate the nature of the failure.
+ *   CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y :
+ *     Called from the NSH library
  *
  ****************************************************************************/
 
-int board_app_initialize(uintptr_t arg)
-{
-  /* Did we already initialize via board_late_initialize()? */
+int rx65n_bringup(void);
 
-#ifndef CONFIG_BOARD_LATE_INITIALIZE
-  return rx65n_bringup();
-#else
-  return OK;
+/****************************************************************************
+ * Name: rx65n_sbsram_int
+ *
+ * Description:
+ *   Initialize SBRAM Driver
+ *
+ *
+ ****************************************************************************/
+#ifdef CONFIG_RX65N_SBRAM
+int rx65n_sbram_int(void);
 #endif
-}
 
-#endif /* CONFIG_LIB_BOARDCTL */
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H */
diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_sbram.c b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_sbram.c
new file mode 100644
index 0000000..fcbc2db
--- /dev/null
+++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_sbram.c
@@ -0,0 +1,490 @@
+/****************************************************************************
+ * boards/renesas/rx65n/rx65n-grrose/src/rx65n_sbram.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+#include <syslog.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/sched.h>
+#include "up_internal.h"
+#include "rx65n_sbram.h"
+#include "rx65n_grrose.h"
+#ifdef CONFIG_RX65N_SBRAM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#define FREEZE_STR(s)          #s
+#define STRINGIFY(s)           FREEZE_STR(s)
+#define HARDFAULT_FILENO       3
+#define HARDFAULT_PATH         SBRAM_PATH""STRINGIFY(HARDFAULT_FILENO)
+#define HARDFAULT_REBOOT_      FILENO 0
+#define HARDFAULT_REBOOT_PATH  SBRAM_PATH""STRINGIFY(HARDFAULT_REBOOT_FILENO)
+
+#define SBRAM_SIZE_FN0        (sizeof(int))
+#define SBRAM_SIZE_FN1        384
+#define SBRAM_SIZE_FN2        384
+#define SBRAM_SIZE_FN3 -      1
+
+/* The following guides in the amount of the user and interrupt stack
+ * data we can save. The amount of storage left will dictate the actual
+ * number of entries of the user stack data saved. If it is too big
+ * It will be truncated by the call to rx65n_sbram_savepanic
+ */
+
+#define SBRAM_HEADER_SIZE     20 /* This is an assumption */
+#define SBRAM_USED            ((4*SBRAM_HEADER_SIZE)+ \
+                                (SBRAM_SIZE_FN0+SBRAM_SIZE_FN1+ \
+                                 SBRAM_SIZE_FN2))
+#define SBRAM_REAMINING       (RX65N_SBRAM_SIZE-SBRAM_USED)
+#if CONFIG_ARCH_INTERRUPTSTACK <= 3
+#  define SBRAM_NUMBER_STACKS 1
+#else
+#  define SBRAM_NUMBER_STACKS 2
+#endif
+#define SBRAM_FIXED_ELEMENTS_SIZE (sizeof(info_t))
+#define SBRAM_LEFTOVER            (SBRAM_REAMINING-\
+                                    SBRAM_FIXED_ELEMENTS_SIZE)
+
+#define CONFIG_ISTACK_SIZE (SBRAM_LEFTOVER/SBRAM_NUMBER_STACKS/ \
+                            sizeof(stack_word_t))
+#define CONFIG_USTACK_SIZE (SBRAM_LEFTOVER/SBRAM_NUMBER_STACKS/ \
+                            sizeof(stack_word_t))
+
+/* The path to the Battery Backed up SRAM */
+
+#define SBRAM_PATH "/fs/sbr"
+
+/* The sizes of the files to create (-1) use rest of SBRAM memory */
+
+#define SBRAM_FILE_SIZES \
+{ \
+  SBRAM_SIZE_FN0, \
+  SBRAM_SIZE_FN1, \
+  SBRAM_SIZE_FN2, \
+  SBRAM_SIZE_FN3, \
+  0 \
+}
+
+#define ARRAYSIZE(a) (sizeof((a))/sizeof(a[0]))
+
+/* For Assert keep this much of the file name */
+
+#define MAX_FILE_PATH_LENGTH 40
+
+#define HEADER_TIME_FMT      "%Y-%m-%d-%H:%M:%S"
+#define HEADER_TIME_FMT_NUM  (2+ 0+ 0+ 0+ 0+ 0)
+#define HEADER_TIME_FMT_LEN  (((ARRAYSIZE(HEADER_TIME_FMT)-1) + \
+                                HEADER_TIME_FMT_NUM))
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Used for stack frame storage */
+
+typedef uint32_t stack_word_t;
+
+/* Stack related data */
+
+typedef struct
+{
+  uint32_t sp;
+  uint32_t top;
+  uint32_t size;
+} _stack_t;
+
+typedef struct
+{
+  _stack_t user;
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+  _stack_t interrupt;
+#endif
+} stack_t;
+
+/* Not Used for reference only */
+
+typedef struct
+{
+  uint32_t sp;
+  uint32_t acc0lo;
+  uint32_t acc0hi;
+  uint32_t acc0gu;
+  uint32_t acc1lo;
+  uint32_t acc1hi;
+  uint32_t acc1gu;
+  uint32_t fpsw;
+  uint32_t r1;
+  uint32_t r2;
+  uint32_t r3;
+  uint32_t r4;
+  uint32_t r5;
+  uint32_t r6;
+  uint32_t r7;
+  uint32_t r8;
+  uint32_t r9;
+  uint32_t r10;
+  uint32_t r11;
+  uint32_t r12;
+  uint32_t r13;
+  uint32_t r14;
+  uint32_t r15;
+  uint32_t pc;
+  uint32_t psw;
+} proc_regs_t;
+
+/* Flags to identify what is in the dump */
+
+typedef enum
+{
+  REGS_PRESENT          = 0x01,
+  USERSTACK_PRESENT     = 0x02,
+  INTSTACK_PRESENT      = 0x04,
+  INVALID_USERSTACK_PTR = 0x20,
+  INVALID_INTSTACK_PTR  = 0x40,
+} fault_flags_t;
+
+typedef struct
+{
+  fault_flags_t flags;                  /* What is in the dump */
+  uintptr_t     current_regs;           /* Used to validate the dump */
+  int           lineno;                 /* __LINE__ to up_assert */
+  int           pid;                    /* Process ID */
+  uint32_t      regs[XCPTCONTEXT_REGS]; /* Interrupt register save area */
+  stack_t       stacks;                 /* Stack info */
+#if CONFIG_TASK_NAME_SIZE > 0
+  char          name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL
+                                                  * terminator) */
+#endif
+  char          filename[MAX_FILE_PATH_LENGTH];  /* the Last of chars in
+                                                  * __FILE__ to up_assert */
+} info_t;
+
+struct fullcontext
+{
+  info_t    info;                  /* The info */
+
+  /* The amount of stack data is compile time
+   * sized backed on what is left after the
+   * other standby ram files are defined
+   * the order is such that only the
+   * ustack should be truncated
+  */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+  stack_word_t istack[CONFIG_USTACK_SIZE];
+#endif
+  stack_word_t ustack[CONFIG_ISTACK_SIZE];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint8_t g_sdata[RX65N_SBRAM_SIZE];
+extern int istack;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: hardfault_get_desc
+ ****************************************************************************/
+
+static int hardfault_get_desc(struct sbramd_s *desc)
+{
+  FAR struct file filestruct;
+  int ret;
+
+  ret = file_open(&filestruct, HARDFAULT_PATH, O_RDONLY);
+  if (ret < 0)
+    {
+      syslog(LOG_INFO, "rx65n sbram: Failed to open Fault Log file [%s] "
+             "(%d)\n", HARDFAULT_PATH, ret);
+    }
+  else
+    {
+      ret = file_ioctl(&filestruct, RX65N_SBRAM_GETDESC_IOCTL,
+                       (unsigned long)((uintptr_t)desc));
+      (void)file_close(&filestruct);
+
+      if (ret < 0)
+        {
+          syslog(LOG_INFO, "rx65n sbram: Failed to get Fault Log descriptor "
+              "(%d)\n", ret);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: copy_reverse
+ ****************************************************************************/
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+static void copy_reverse(stack_word_t *dest, stack_word_t *src, int size)
+{
+  while (size--)
+    {
+      *dest++ = *src--;
+    }
+}
+#endif /* CONFIG_RX65N_SAVE_CRASHDUMP */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rx65n_sbram_int
+ ****************************************************************************/
+
+int rx65n_sbram_int(void)
+{
+  int filesizes[CONFIG_RX65N_SBRAM_FILES + 1] = SBRAM_FILE_SIZES;
+  char buf[HEADER_TIME_FMT_LEN + 1];
+  struct sbramd_s desc;
+  int rv;
+  int state;
+  struct tm tt;
+  time_t time_sec;
+
+  /* Using Standby RAM */
+
+  rx65n_sbraminitialize(SBRAM_PATH, filesizes);
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+  /* Panic Logging in Battery Backed Up Files */
+
+  /* Do we have an hard fault in SBRAM? */
+
+  rv = hardfault_get_desc(&desc);
+  if (rv >= OK)
+    {
+      syslog(LOG_EMERG, "There is a hard fault logged.\n");
+      state = (desc.lastwrite.tv_sec || desc.lastwrite.tv_nsec) ?  OK : 1;
+
+      syslog(LOG_INFO, "Fault Log info File No %d Length %d flags:0x%02x "
+          "state:%d\n", (unsigned int)desc.fileno, (unsigned int) desc.len,
+          (unsigned int)desc.flags, state);
+
+      if (state == OK)
+        {
+          time_sec = desc.lastwrite.tv_sec + (desc.lastwrite.tv_nsec / 1e9);
+          gmtime_r(&time_sec, &tt);
+          strftime(buf, HEADER_TIME_FMT_LEN , HEADER_TIME_FMT , &tt);
+
+          syslog(LOG_INFO, "Fault Logged on %s - Valid\n", buf);
+        }
+
+      rv = unlink(HARDFAULT_PATH);
+      if (rv < 0)
+        {
+          syslog(LOG_INFO, "rx65n sbram: Failed to unlink Fault Log file [%s"
+                 "] (%d)\n", HARDFAULT_PATH, rv);
+        }
+    }
+
+#endif /* CONFIG_RX65N_SAVE_CRASHDUMP */
+
+  return rv;
+}
+
+/****************************************************************************
+ * Name: board_crashdump
+ ****************************************************************************/
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+void board_crashdump(uintptr_t currentsp, FAR void *tcb,
+                     FAR const uint8_t *filename, int lineno)
+{
+  struct fullcontext *pdump ;
+  pdump = (struct fullcontext *)&g_sdata;
+  FAR struct tcb_s *rtcb;
+  int rv;
+
+  (void)enter_critical_section();
+
+  rtcb = (FAR struct tcb_s *)tcb;
+
+  /* Zero out everything */
+
+  memset((uint8_t *)pdump, 0, sizeof(struct fullcontext));
+
+  /* Save Info */
+
+  pdump->info.lineno = lineno;
+
+  if (filename)
+    {
+      int offset = 0;
+      unsigned int len = strlen((char *)filename) + 1;
+
+      if (len > sizeof(pdump->info.filename))
+        {
+          offset = len - sizeof(pdump->info.filename);
+        }
+
+      strncpy((char *)pdump->info.filename, (char *)&filename[offset],
+              sizeof(pdump->info.filename));
+    }
+
+  /* Save the value of the pointer for current_regs as debugging info.
+   * It should be NULL in case of an ASSERT and will aid in cross
+   * checking the validity of system memory at the time of the
+   * fault.
+   */
+
+  pdump->info.current_regs = (uintptr_t) g_current_regs;
+
+  /* Save Context */
+
+#if CONFIG_TASK_NAME_SIZE > 0
+  strncpy(pdump->info.name, rtcb->name, CONFIG_TASK_NAME_SIZE);
+#endif
+
+  pdump->info.pid = rtcb->pid;
+
+  /* If  current_regs is not NULL then we are in an interrupt context
+   * and the user context is in current_regs else we are running in
+   * the users context
+   */
+
+  if (g_current_regs)
+    {
+      pdump->info.stacks.interrupt.sp = currentsp;
+      pdump->info.flags |= (REGS_PRESENT | USERSTACK_PRESENT | \
+                            INTSTACK_PRESENT);
+      memcpy((uint8_t *)pdump->info.regs, (void *)g_current_regs,
+             sizeof(pdump->info.regs));
+      pdump->info.stacks.user.sp = pdump->info.regs[REG_SP];
+    }
+  else
+    {
+      /* users context */
+
+      pdump->info.flags |= USERSTACK_PRESENT;
+      pdump->info.stacks.user.sp = currentsp;
+    }
+
+  if (pdump->info.pid == 0)
+    {
+      pdump->info.stacks.user.top = g_idle_topstack - 4;
+      pdump->info.stacks.user.size = CONFIG_IDLETHREAD_STACKSIZE;
+    }
+  else
+    {
+      pdump->info.stacks.user.top = (uint32_t) rtcb->adj_stack_ptr;
+      pdump->info.stacks.user.size = (uint32_t) rtcb->adj_stack_size;
+    }
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+  /* Get the limits on the interrupt stack memory */
+
+  pdump->info.stacks.interrupt.top = (uint32_t)&istack;
+  pdump->info.stacks.interrupt.size  = (CONFIG_ARCH_INTERRUPTSTACK);
+
+  /* If In interrupt Context save the interrupt stack data centered
+   * about the interrupt stack pointer
+   */
+
+  if ((pdump->info.flags & INTSTACK_PRESENT) != 0)
+    {
+      stack_word_t *ps = (stack_word_t *) pdump->info.stacks.interrupt.sp;
+      copy_reverse((stack_word_t *)pdump->istack,
+                        &ps[ARRAYSIZE(pdump->istack) / 2],
+                    ARRAYSIZE(pdump->istack));
+    }
+
+  /* Is it Invalid? */
+
+  if (!(pdump->info.stacks.interrupt.sp <= pdump->info.stacks.interrupt.top
+       && pdump->info.stacks.interrupt.sp >
+           pdump->info.stacks.interrupt.top -
+       pdump->info.stacks.interrupt.size))
+    {
+      pdump->info.flags |= INVALID_INTSTACK_PTR;
+    }
+
+#endif
+  /* If In interrupt context or User save the user stack data centered
+   * about the user stack pointer
+   */
+
+  if ((pdump->info.flags & USERSTACK_PRESENT) != 0)
+    {
+      stack_word_t *ps = (stack_word_t *) pdump->info.stacks.user.sp;
+      copy_reverse((stack_word_t *)pdump->ustack,
+                        &ps[ARRAYSIZE(pdump->ustack) / 2],
+                    ARRAYSIZE(pdump->ustack));
+    }
+
+  /* Is it Invalid? */
+
+  if (!(pdump->info.stacks.user.sp <= pdump->info.stacks.user.top &&
+        pdump->info.stacks.user.sp > pdump->info.stacks.user.top -
+          pdump->info.stacks.user.size))
+    {
+      pdump->info.flags |= INVALID_USERSTACK_PTR;
+    }
+
+  rv = rx65n_sbram_savepanic(HARDFAULT_FILENO, (uint8_t *)pdump,
+                              sizeof(struct fullcontext));
+
+  /* Test if memory got wiped because of using _sdata */
+
+  if (rv == -ENXIO)
+    {
+      char *dead = "Memory wiped - dump not saved!";
+
+      while (*dead)
+        {
+          up_lowputc(*dead++);
+        }
+    }
+  else if (rv == -ENOSPC)
+    {
+      /* hard fault again */
+
+      up_lowputc('!');
+    }
+}
+#endif /* CONFIG_RX65N_SAVE_CRASHDUMP */
+
+#endif /* CONFIG_RX65N_SBRAM */
diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/src/Makefile b/boards/renesas/rx65n/rx65n-rsk2mb/src/Makefile
index 162e488..801c80f 100644
--- a/boards/renesas/rx65n/rx65n-rsk2mb/src/Makefile
+++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/Makefile
@@ -26,7 +26,7 @@ CFLAGS += -I=$(ARCH_SRCDIR)/chip
 
 ASRCS =
 AOBJS = $(ASRCS:.asm=$(OBJEXT))
-CSRCS = rx65n_appinit.c rx65n_bringup.c
+CSRCS = rx65n_appinit.c rx65n_bringup.c rx65n_sbram.c
 COBJS = $(CSRCS:.c=$(OBJEXT))
 
 SRCS = $(ASRCS) $(CSRCS)
diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c
index b29e7fb..1a0a353 100644
--- a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c
+++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_bringup.c
@@ -34,6 +34,7 @@
 
 #include <nuttx/board.h>
 
+#include "rx65n_rsk2mb.h"
 #include <rx65n_definitions.h>
 #ifdef CONFIG_LIB_BOARDCTL
 
@@ -123,6 +124,12 @@ int rx65n_bringup(void)
     }
 
 #endif
+
+#ifdef CONFIG_RX65N_SBRAM
+  /* Initialize standby RAM */
+
+  (void)rx65n_sbram_int();
+#endif
   return OK;
 }
 
diff --git a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h
similarity index 50%
copy from boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
copy to boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h
index 20e093e..350d9d0 100644
--- a/boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
+++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/renesas/rx65n/rx65n-grrose/src/rx65n_appinit.c
+ * boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,64 +18,58 @@
  *
  ****************************************************************************/
 
+#ifndef __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H
+#define __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
-
-#include <sys/types.h>
+#include <nuttx/compiler.h>
 #include <stdint.h>
 
-#include <nuttx/board.h>
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
 
-#ifdef CONFIG_LIB_BOARDCTL
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
 
 /****************************************************************************
- * Public Functions
+ * Public data
  ****************************************************************************/
 
+#ifndef __ASSEMBLY__
+
 /****************************************************************************
- * Name: board_app_initialize
+ * Name: rx65n_bringup
  *
  * Description:
- *   Perform application specific initialization.  This function is never
- *   called directly from application code, but only indirectly via the
- *   (non-standard) boardctl() interface using the command BOARDIOC_INIT.
- *
- *   CONFIG_LIB_BOARDCTL=y :
- *     Called from the NSH library
+ *   Perform architecture-specific initialization
  *
- *   CONFIG_BOARD_LATE_INITIALIZE=y, CONFIG_NSH_LIBRARY=y, &&
- *   CONFIG_LIB_BOARDCTL=n :
+ *   CONFIG_BOARD_LATE_INITIALIZE=y :
  *     Called from board_late_initialize().
  *
- * Input Parameters:
- *   arg - The boardctl() argument is passed to the board_app_initialize()
- *         implementation without modification.  The argument has no
- *         meaning to NuttX; the meaning of the argument is a contract
- *         between the board-specific initialization logic and the
- *         matching application logic.  The value cold be such things as a
- *         mode enumeration value, a set of DIP switch switch settings, a
- *         pointer to configuration data read from a file or serial FLASH,
- *         or whatever you would like to do with it.  Every implementation
- *         should accept zero/NULL as a default configuration.
- *
- * Returned Value:
- *   Zero (OK) is returned on success; a negated errno value is returned on
- *   any failure to indicate the nature of the failure.
+ *   CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y :
+ *     Called from the NSH library
  *
  ****************************************************************************/
 
-int board_app_initialize(uintptr_t arg)
-{
-  /* Did we already initialize via board_late_initialize()? */
+int rx65n_bringup(void);
 
-#ifndef CONFIG_BOARD_LATE_INITIALIZE
-  return rx65n_bringup();
-#else
-  return OK;
+/****************************************************************************
+ * Name: rx65n_sbsram_int
+ *
+ * Description:
+ *   Initialize SBRAM Driver
+ *
+ *
+ ****************************************************************************/
+#ifdef CONFIG_RX65N_SBRAM
+int rx65n_sbram_int(void);
 #endif
-}
 
-#endif /* CONFIG_LIB_BOARDCTL */
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H */
diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_sbram.c b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_sbram.c
new file mode 100644
index 0000000..4c25271
--- /dev/null
+++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_sbram.c
@@ -0,0 +1,487 @@
+/****************************************************************************
+ * boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_sbram.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+#include <syslog.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/sched.h>
+#include "up_internal.h"
+#include "rx65n_sbram.h"
+#include "rx65n_rsk2mb.h"
+#ifdef CONFIG_RX65N_SBRAM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#define FREEZE_STR(s)          #s
+#define STRINGIFY(s)           FREEZE_STR(s)
+#define HARDFAULT_FILENO       3
+#define HARDFAULT_PATH         SBRAM_PATH""STRINGIFY(HARDFAULT_FILENO)
+#define HARDFAULT_REBOOT_      FILENO 0
+#define HARDFAULT_REBOOT_PATH  SBRAM_PATH""STRINGIFY(HARDFAULT_REBOOT_FILENO)
+
+#define SBRAM_SIZE_FN0        (sizeof(int))
+#define SBRAM_SIZE_FN1        384
+#define SBRAM_SIZE_FN2        384
+#define SBRAM_SIZE_FN3 -      1
+
+/* The following guides in the amount of the user and interrupt stack
+ * data we can save. The amount of storage left will dictate the actual
+ * number of entries of the user stack data saved. If it is too big
+ * It will be truncated by the call to rx65n_sbram_savepanic
+ */
+
+#define SBRAM_HEADER_SIZE     20 /* This is an assumption */
+#define SBRAM_USED            ((4*SBRAM_HEADER_SIZE)+ \
+                                (SBRAM_SIZE_FN0+SBRAM_SIZE_FN1+ \
+                                 SBRAM_SIZE_FN2))
+#define SBRAM_REAMINING       (RX65N_SBRAM_SIZE-SBRAM_USED)
+#if CONFIG_ARCH_INTERRUPTSTACK <= 3
+#  define SBRAM_NUMBER_STACKS 1
+#else
+#  define SBRAM_NUMBER_STACKS 2
+#endif
+#define SBRAM_FIXED_ELEMENTS_SIZE (sizeof(info_t))
+#define SBRAM_LEFTOVER            (SBRAM_REAMINING-\
+                                    SBRAM_FIXED_ELEMENTS_SIZE)
+
+#define CONFIG_ISTACK_SIZE (SBRAM_LEFTOVER/SBRAM_NUMBER_STACKS/ \
+                            sizeof(stack_word_t))
+#define CONFIG_USTACK_SIZE (SBRAM_LEFTOVER/SBRAM_NUMBER_STACKS/ \
+                            sizeof(stack_word_t))
+
+/* The path to the Standby RAM */
+
+#define SBRAM_PATH "/fs/sbr"
+
+/* The sizes of the files to create (-1) use rest of SBRAM memory */
+
+#define SBRAM_FILE_SIZES \
+{ \
+  SBRAM_SIZE_FN0, \
+  SBRAM_SIZE_FN1, \
+  SBRAM_SIZE_FN2, \
+  SBRAM_SIZE_FN3, \
+  0 \
+}
+
+#define ARRAYSIZE(a) (sizeof((a))/sizeof(a[0]))
+
+/* For Assert keep this much of the file name */
+
+#define MAX_FILE_PATH_LENGTH 40
+
+#define HEADER_TIME_FMT      "%Y-%m-%d-%H:%M:%S"
+#define HEADER_TIME_FMT_NUM  (2+ 0+ 0+ 0+ 0+ 0)
+#define HEADER_TIME_FMT_LEN  (((ARRAYSIZE(HEADER_TIME_FMT)-1) + \
+                                HEADER_TIME_FMT_NUM))
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Used for stack frame storage */
+
+typedef uint32_t stack_word_t;
+
+/* Stack related data */
+
+typedef struct
+{
+  uint32_t sp;
+  uint32_t top;
+  uint32_t size;
+} _stack_t;
+
+typedef struct
+{
+  _stack_t user;
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+  _stack_t interrupt;
+#endif
+} stack_t;
+
+/* Not Used for reference only */
+
+typedef struct
+{
+  uint32_t sp;
+  uint32_t acc0lo;
+  uint32_t acc0hi;
+  uint32_t acc0gu;
+  uint32_t acc1lo;
+  uint32_t acc1hi;
+  uint32_t acc1gu;
+  uint32_t fpsw;
+  uint32_t r1;
+  uint32_t r2;
+  uint32_t r3;
+  uint32_t r4;
+  uint32_t r5;
+  uint32_t r6;
+  uint32_t r7;
+  uint32_t r8;
+  uint32_t r9;
+  uint32_t r10;
+  uint32_t r11;
+  uint32_t r12;
+  uint32_t r13;
+  uint32_t r14;
+  uint32_t r15;
+  uint32_t pc;
+  uint32_t psw;
+} proc_regs_t;
+
+/* Flags to identify what is in the dump */
+
+typedef enum
+{
+  REGS_PRESENT          = 0x01,
+  USERSTACK_PRESENT     = 0x02,
+  INTSTACK_PRESENT      = 0x04,
+  INVALID_USERSTACK_PTR = 0x20,
+  INVALID_INTSTACK_PTR  = 0x40,
+} fault_flags_t;
+
+typedef struct
+{
+  fault_flags_t flags;                  /* What is in the dump */
+  uintptr_t     current_regs;           /* Used to validate the dump */
+  int           lineno;                 /* __LINE__ to up_assert */
+  int           pid;                    /* Process ID */
+  uint32_t      regs[XCPTCONTEXT_REGS]; /* Interrupt register save area */
+  stack_t       stacks;                 /* Stack info */
+#if CONFIG_TASK_NAME_SIZE > 0
+  char          name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL
+                                                  * terminator) */
+#endif
+  char          filename[MAX_FILE_PATH_LENGTH];  /* the Last of chars in
+                                                  * __FILE__ to up_assert */
+} info_t;
+
+struct fullcontext
+{
+  info_t    info;                  /* The info */
+
+  /* The amount of stack data is compile time sized backed on what is left
+   * after the other standby ram files are defined the order is such that
+   * only the ustack should be truncated
+   */
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+  stack_word_t istack[CONFIG_USTACK_SIZE];
+#endif
+  stack_word_t ustack[CONFIG_ISTACK_SIZE];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint8_t g_sdata[RX65N_SBRAM_SIZE];
+extern int istack;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: hardfault_get_desc
+ ****************************************************************************/
+
+static int hardfault_get_desc(struct sbramd_s *desc)
+{
+  FAR struct file filestruct;
+  int ret;
+
+  ret = file_open(&filestruct, HARDFAULT_PATH, O_RDONLY);
+  if (ret < 0)
+    {
+      syslog(LOG_INFO, "rx65n sbram: Failed to open Fault Log file [%s] "
+             "(%d)\n", HARDFAULT_PATH, ret);
+    }
+  else
+    {
+      ret = file_ioctl(&filestruct, RX65N_SBRAM_GETDESC_IOCTL,
+                       (unsigned long)((uintptr_t)desc));
+      (void)file_close(&filestruct);
+
+      if (ret < 0)
+        {
+          syslog(LOG_INFO, "rx65n sbram: Failed to get Fault Log descriptor "
+              "(%d)\n", ret);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: copy_reverse
+ ****************************************************************************/
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+static void copy_reverse(stack_word_t *dest, stack_word_t *src, int size)
+{
+  while (size--)
+    {
+      *dest++ = *src--;
+    }
+}
+#endif /* CONFIG_RX65N_SAVE_CRASHDUMP */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: rx65n_sbram_int
+ ****************************************************************************/
+
+int rx65n_sbram_int(void)
+{
+  int filesizes[CONFIG_RX65N_SBRAM_FILES + 1] = SBRAM_FILE_SIZES;
+  char buf[HEADER_TIME_FMT_LEN + 1];
+  struct sbramd_s desc;
+  int rv;
+  int state;
+  struct tm tt;
+  time_t time_sec;
+
+  /* Using Standby RAM */
+
+  rx65n_sbraminitialize(SBRAM_PATH, filesizes);
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+  /* Panic Logging in Standby RAM Files */
+
+  /* Do we have an hard fault in SBRAM? */
+
+  rv = hardfault_get_desc(&desc);
+  if (rv >= OK)
+    {
+      syslog(LOG_EMERG, "There is a hard fault logged.\n");
+      state = (desc.lastwrite.tv_sec || desc.lastwrite.tv_nsec) ?  OK : 1;
+
+      syslog(LOG_INFO, "Fault Log info File No %d Length %d flags:0x%02x "
+          "state:%d\n", (unsigned int)desc.fileno, (unsigned int) desc.len,
+          (unsigned int)desc.flags, state);
+
+      if (state == OK)
+        {
+          time_sec = desc.lastwrite.tv_sec + (desc.lastwrite.tv_nsec / 1e9);
+          gmtime_r(&time_sec, &tt);
+          strftime(buf, HEADER_TIME_FMT_LEN , HEADER_TIME_FMT , &tt);
+
+          syslog(LOG_INFO, "Fault Logged on %s - Valid\n", buf);
+        }
+
+      rv = unlink(HARDFAULT_PATH);
+      if (rv < 0)
+        {
+          syslog(LOG_INFO, "rx65n sbram: Failed to unlink Fault Log file [%s"
+                 "] (%d)\n", HARDFAULT_PATH, rv);
+        }
+    }
+
+#endif /* CONFIG_RX65N_SAVE_CRASHDUMP */
+
+  return rv;
+}
+
+/****************************************************************************
+ * Name: board_crashdump
+ ****************************************************************************/
+
+#if defined(CONFIG_RX65N_SAVE_CRASHDUMP)
+void board_crashdump(uintptr_t currentsp, FAR void *tcb,
+                     FAR const uint8_t *filename, int lineno)
+{
+  struct fullcontext *pdump ;
+  pdump = (struct fullcontext *)&g_sdata;
+  FAR struct tcb_s *rtcb;
+  int rv;
+
+  (void)enter_critical_section();
+
+  rtcb = (FAR struct tcb_s *)tcb;
+
+  /* Zero out everything */
+
+  memset((uint8_t *)pdump, 0, sizeof(struct fullcontext));
+
+  /* Save Info */
+
+  pdump->info.lineno = lineno;
+
+  if (filename)
+    {
+      int offset = 0;
+      unsigned int len = strlen((char *)filename) + 1;
+
+      if (len > sizeof(pdump->info.filename))
+        {
+          offset = len - sizeof(pdump->info.filename);
+        }
+
+      strncpy((char *)pdump->info.filename, (char *)&filename[offset],
+              sizeof(pdump->info.filename));
+    }
+
+  /* Save the value of the pointer for current_regs as debugging info.
+   * It should be NULL in case of an ASSERT and will aid in cross
+   * checking the validity of system memory at the time of the
+   * fault.
+   */
+
+  pdump->info.current_regs = (uintptr_t) g_current_regs;
+
+  /* Save Context */
+
+#if CONFIG_TASK_NAME_SIZE > 0
+  strncpy(pdump->info.name, rtcb->name, CONFIG_TASK_NAME_SIZE);
+#endif
+
+  pdump->info.pid = rtcb->pid;
+
+  /* If  current_regs is not NULL then we are in an interrupt context
+   * and the user context is in current_regs else we are running in
+   * the users context
+   */
+
+  if (g_current_regs)
+    {
+      pdump->info.stacks.interrupt.sp = currentsp;
+      pdump->info.flags |= (REGS_PRESENT | USERSTACK_PRESENT | \
+                            INTSTACK_PRESENT);
+      memcpy((uint8_t *)pdump->info.regs, (void *)g_current_regs,
+             sizeof(pdump->info.regs));
+      pdump->info.stacks.user.sp = pdump->info.regs[REG_SP];
+    }
+  else
+    {
+      /* users context */
+
+      pdump->info.flags |= USERSTACK_PRESENT;
+      pdump->info.stacks.user.sp = currentsp;
+    }
+
+  if (pdump->info.pid == 0)
+    {
+      pdump->info.stacks.user.top = g_idle_topstack - 4;
+      pdump->info.stacks.user.size = CONFIG_IDLETHREAD_STACKSIZE;
+    }
+  else
+    {
+      pdump->info.stacks.user.top = (uint32_t) rtcb->adj_stack_ptr;
+      pdump->info.stacks.user.size = (uint32_t) rtcb->adj_stack_size;
+    }
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+  /* Get the limits on the interrupt stack memory */
+
+  pdump->info.stacks.interrupt.top = (uint32_t)&istack;
+  pdump->info.stacks.interrupt.size  = (CONFIG_ARCH_INTERRUPTSTACK);
+
+  /* If In interrupt Context save the interrupt stack data centered
+   * about the interrupt stack pointer
+   */
+
+  if ((pdump->info.flags & INTSTACK_PRESENT) != 0)
+    {
+      stack_word_t *ps = (stack_word_t *) pdump->info.stacks.interrupt.sp;
+      copy_reverse((stack_word_t *)pdump->istack,
+                        &ps[ARRAYSIZE(pdump->istack) / 2],
+                    ARRAYSIZE(pdump->istack));
+    }
+
+  /* Is it Invalid? */
+
+  if (!(pdump->info.stacks.interrupt.sp <= pdump->info.stacks.interrupt.top
+    && pdump->info.stacks.interrupt.sp > pdump->info.stacks.interrupt.top -
+          pdump->info.stacks.interrupt.size))
+    {
+      pdump->info.flags |= INVALID_INTSTACK_PTR;
+    }
+
+#endif
+  /* If In interrupt context or User save the user stack data centered
+   * about the user stack pointer
+   */
+
+  if ((pdump->info.flags & USERSTACK_PRESENT) != 0)
+    {
+      stack_word_t *ps = (stack_word_t *) pdump->info.stacks.user.sp;
+      copy_reverse((stack_word_t *)pdump->ustack,
+                        &ps[ARRAYSIZE(pdump->ustack) / 2],
+                    ARRAYSIZE(pdump->ustack));
+    }
+
+  /* Is it Invalid? */
+
+  if (!(pdump->info.stacks.user.sp <= pdump->info.stacks.user.top &&
+        pdump->info.stacks.user.sp > pdump->info.stacks.user.top -
+          pdump->info.stacks.user.size))
+    {
+      pdump->info.flags |= INVALID_USERSTACK_PTR;
+    }
+
+  rv = rx65n_sbram_savepanic(HARDFAULT_FILENO, (uint8_t *)pdump,
+                              sizeof(struct fullcontext));
+
+  /* Test if memory got wiped because of using _sdata */
+
+  if (rv == -ENXIO)
+    {
+      char *dead = "Memory wiped - dump not saved!";
+
+      while (*dead)
+        {
+          up_lowputc(*dead++);
+        }
+    }
+  else if (rv == -ENOSPC)
+    {
+      /* hard fault again */
+
+      up_lowputc('!');
+    }
+}
+#endif /* CONFIG_RX65N_SAVE_CRASHDUMP */
+
+#endif /* CONFIG_RX65N_SBRAM */