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