From 31332904dd10b7d0e8060e1a667f250888ec9aa4 Mon Sep 17 00:00:00 2001 From: rajeshwaribhat Date: Tue, 21 Apr 2020 16:39:21 +0530 Subject: [PATCH] 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 ++++ .../renesas/rx65n/rx65n-grrose/src/Makefile | 2 +- .../rx65n/rx65n-grrose/src/rx65n_appinit.c | 3 +- .../rx65n/rx65n-grrose/src/rx65n_bringup.c | 9 +- .../rx65n/rx65n-grrose/src/rx65n_grrose.h | 75 ++ .../rx65n/rx65n-grrose/src/rx65n_sbram.c | 490 +++++++++++ .../renesas/rx65n/rx65n-rsk2mb/src/Makefile | 2 +- .../rx65n/rx65n-rsk2mb/src/rx65n_bringup.c | 7 + .../rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h | 75 ++ .../rx65n/rx65n-rsk2mb/src/rx65n_sbram.c | 487 +++++++++++ 15 files changed, 2150 insertions(+), 40 deletions(-) create mode 100644 arch/renesas/src/rx65n/rx65n_sbram.c create mode 100644 arch/renesas/src/rx65n/rx65n_sbram.h create mode 100644 boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h create mode 100644 boards/renesas/rx65n/rx65n-grrose/src/rx65n_sbram.c create mode 100644 boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h create mode 100644 boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_sbram.c diff --git a/arch/renesas/src/rx65n/Kconfig b/arch/renesas/src/rx65n/Kconfig index 676ca4915e..7d211a9357 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 07b26731a7..31cc58280f 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 5a9a2e08f7..ee6fa5fca9 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 20c4556c86..e72cdd4dd6 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 + * 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 0000000000..1e3ec8954b --- /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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 0000000000..f1487ee9ed --- /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 +#include + +/**************************************************************************** + * 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 645bbe7fee..3cf1dfb5ca 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 20e093e37b..4feccfe383 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 #include +#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 043f62af06..c83b3487a2 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 +#include "rx65n_grrose.h" #include #ifdef CONFIG_LIB_BOARDCTL @@ -122,6 +123,12 @@ int rx65n_bringup(void) ret, errno); } +#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_grrose.h b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h new file mode 100644 index 0000000000..eb5504414d --- /dev/null +++ b/boards/renesas/rx65n/rx65n-grrose/src/rx65n_grrose.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * 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 + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H +#define __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: rx65n_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y : + * Called from the NSH library + * + ****************************************************************************/ + +int rx65n_bringup(void); + +/**************************************************************************** + * Name: rx65n_sbsram_int + * + * Description: + * Initialize SBRAM Driver + * + * + ****************************************************************************/ +#ifdef CONFIG_RX65N_SBRAM +int rx65n_sbram_int(void); +#endif + +#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 0000000000..fcbc2db441 --- /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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#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 162e488315..801c80fb0b 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 b29e7fb7cd..1a0a353628 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 +#include "rx65n_rsk2mb.h" #include #ifdef CONFIG_LIB_BOARDCTL @@ -122,6 +123,12 @@ int rx65n_bringup(void) ret, errno); } +#endif + +#ifdef CONFIG_RX65N_SBRAM + /* Initialize standby RAM */ + + (void)rx65n_sbram_int(); #endif return OK; } diff --git a/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h new file mode 100644 index 0000000000..350d9d0363 --- /dev/null +++ b/boards/renesas/rx65n/rx65n-rsk2mb/src/rx65n_rsk2mb.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * 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 + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H +#define __BOARDS_RENESAS_RX65N_GRROSE_SRC_RX65N_GRROSE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: rx65n_bringup + * + * Description: + * Perform architecture-specific initialization + * + * CONFIG_BOARD_LATE_INITIALIZE=y : + * Called from board_late_initialize(). + * + * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y : + * Called from the NSH library + * + ****************************************************************************/ + +int rx65n_bringup(void); + +/**************************************************************************** + * Name: rx65n_sbsram_int + * + * Description: + * Initialize SBRAM Driver + * + * + ****************************************************************************/ +#ifdef CONFIG_RX65N_SBRAM +int rx65n_sbram_int(void); +#endif + +#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 0000000000..4c25271a63 --- /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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#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 */