diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 9a61e8e89a..8740208e9e 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -1134,7 +1134,7 @@ config STM32_BKP depends on STM32_STM32F10XX config STM32_BKPSRAM - bool "BKP RAM" + bool "Enable BKP RAM Domain" default n depends on STM32_STM32F207 || STM32_STM32F40XX @@ -3254,6 +3254,22 @@ config SDIO_WIDTH_D1_ONLY endmenu +if STM32_BKPSRAM + +config STM32_BBSRAM + bool "BBSRAM File Support" + default n + +config STM32_BBSRAM_FILES + int "Max Files to support in BBSRAM" + default 4 + +config STM32_SAVE_CRASHDUMP + bool "Enable Saving Panic to BBSRAM" + default n + +endif # STM32_BKPSRAM + config STM32_HAVE_RTC_SUBSECONDS bool default n diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs index a6b4e874e6..a4ee123d30 100644 --- a/arch/arm/src/stm32/Make.defs +++ b/arch/arm/src/stm32/Make.defs @@ -233,3 +233,7 @@ endif ifeq ($(CONFIG_STM32_AES),y) CHIP_CSRCS += stm32_aes.c endif + +ifeq ($(CONFIG_STM32_BBSRAM),y) +CHIP_CSRCS += stm32_bbsram.c +endif diff --git a/arch/arm/src/stm32/stm32_bbsram.c b/arch/arm/src/stm32/stm32_bbsram.c new file mode 100644 index 0000000000..66f834966b --- /dev/null +++ b/arch/arm/src/stm32/stm32_bbsram.c @@ -0,0 +1,861 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_bbsram.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 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. + * + ****************************************************************************/ + +/* This will driver create a set of files in the STM32'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 "stm32_bbsram.h" +#include "chip.h" +#include "stm32_pwr.h" +#include "stm32_rtc.h" + +#ifdef CONFIG_STM32_BBSRAM + +/**************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +#if !defined(CONFIG_STM32_BKPSRAM) +#error Driver Requires CONFIG_STM32_BKPSRAM to be enabled +#endif + +#define MAX_OPENCNT (255) /* Limit of uint8_t */ + +#if defined(CONFIG_BBSRAM_DEBUG) +# define BBSRAM_DEBUG_READ() stm32_bbsram_rd() +# define BBSRAM_DUMP(p,s) stm32_bbsram_dump(p,s) +#else +# define BBSRAM_DEBUG_READ() +# define BBSRAM_DUMP(p,s) +#endif + +#define BBSRAM_HEADER_SIZE (sizeof(struct bbsramfh_s)) +#define BBSRAM_CRCED_OFFSET (sizeof(((struct bbsramfh_s *)0)->crc)) +#define BBSRAM_CRCED_SIZE(l) (BBSRAM_HEADER_SIZE-BBSRAM_CRCED_OFFSET+(l)) +#define BBSRAM_ALIGNMENT (sizeof(((struct bbsramfh_s *)0)->crc)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* File Header */ + +struct bbsramfh_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 stm32_bbsram_s +{ + sem_t exclsem; /* For atomic accesses to this structure */ + uint8_t refs; /* Number of references */ + FAR struct bbsramfh_s *bbf; /* File in bbram */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int stm32_bbsram_open(FAR struct file *filep); +static int stm32_bbsram_close(FAR struct file *filep); +static off_t stm32_bbsram_seek(FAR struct file *filep, off_t offset, int whence); +static ssize_t stm32_bbsram_read(FAR struct file *, FAR char *, size_t); +static ssize_t stm32_bbsram_write(FAR struct file *, FAR const char *, size_t); +static int stm32_bbsram_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int stm32_bbsram_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int stm32_bbsram_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_BBSRAM_DEBUG) +static uint8_t debug[STM32_BBSRAM_SIZE]; +#endif + +static const struct file_operations stm32_bbsram_fops = +{ + .open = stm32_bbsram_open, + .close = stm32_bbsram_close, + .read = stm32_bbsram_read, + .write = stm32_bbsram_write, + .seek = stm32_bbsram_seek, + .ioctl = stm32_bbsram_ioctl, +#ifndef CONFIG_DISABLE_POLL + .poll = stm32_bbsram_poll, +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + .unlink = stm32_bbsram_unlink, +#endif +}; + +static struct stm32_bbsram_s g_bbsram[CONFIG_STM32_BBSRAM_FILES]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: stm32_bbsram_rd + ****************************************************************************/ + +#if defined(CONFIG_BBSRAM_DEBUG) +static void stm32_bbsram_rd(void) +{ + memcpy(&debug,(uint8_t*)STM32_BKPSRAM_BASE,sizeof debug); +} +#endif + +/**************************************************************************** + * Name: stm32_bbsram_rd + ****************************************************************************/ + +#if defined(CONFIG_BBSRAM_DEBUG) +static void stm32_bbsram_dump(FAR struct bbsramfh_s *bbf, char *op) +{ + BBSRAM_DEBUG_READ(); + lldbg("%s:\n",op); + lldbg(" File Address:0x%8x\n", bbf); + lldbg(" crc:0x%8x\n", bbf->crc); + lldbg(" fileno:%d\n", (int) bbf->fileno); + lldbg(" dirty:%d\n", (int) bbf->dirty); + lldbg(" length:%d\n", (int) bbf->len); + lldbg(" time:%ld:%ld\n", bbf->lastwrite.tv_sec, bbf->lastwrite.tv_nsec); + lldbg(" 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: stm32_bbsram_semgive + ************************************************************************************/ + +static void stm32_bbsram_semgive(FAR struct stm32_bbsram_s *priv) +{ + sem_post(&priv->exclsem); +} + +/************************************************************************************ + * Name: stm32_bbsram_semtake + * + * Description: + * Take a semaphore handling any exceptional conditions + * + * Input Parameters: + * priv - A reference to the CAN peripheral state + * + * Returned Value: + * None + * +****************************************************************************/ + +static void stm32_bbsram_semtake(FAR struct stm32_bbsram_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 = sem_wait(&priv->exclsem); + DEBUGASSERT(ret == 0 || errno == EINTR); + } + while (ret < 0); +} + +/**************************************************************************** + * Name: stm32_bbsram_ulock + * + * Description: + * Unprotects RTC registers, RTC backup data registers and backup SRAM + * against parasitic write access + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void stm32_bbsram_unlock(void) +{ + stm32_pwr_enablebkp(true); +} + +/**************************************************************************** + * Name: stm32_bbsram_lock + * + * Description: + * Protects RTC registers, RTC backup data registers and backup SRAM + * against parasitic write access + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void stm32_bbsram_lock(void) +{ + stm32_pwr_enablebkp(false); +} + +/**************************************************************************** + * Name: stm32_bbsram_crc + * + * Description: + * Calculates the CRC of the block + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static uint32_t stm32_bbsram_crc(FAR struct bbsramfh_s *pf) +{ + return crc32((uint8_t*)pf + BBSRAM_CRCED_OFFSET, BBSRAM_CRCED_SIZE(pf->len)); +} + +/**************************************************************************** + * Name: stm32_bbsram_open + * + * Description: Open the device + * + ****************************************************************************/ + +static int stm32_bbsram_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct stm32_bbsram_s *bbr; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_s *)inode->i_private; + + /* Increment the reference count */ + + stm32_bbsram_semtake(bbr); + if (bbr->refs == MAX_OPENCNT) + { + return -EMFILE; + } + else + { + bbr->refs++; + } + + stm32_bbsram_semgive(bbr); + return OK; +} + +/**************************************************************************** + * Name: stm32_bbsram_internal_close + * + * Description: + * Close BBSRAM entry; Recalculate the time and crc + * + ****************************************************************************/ + +static int stm32_bbsram_internal_close(FAR struct bbsramfh_s *bbf) +{ + bbf->dirty = 0; + (void)clock_gettime(CLOCK_REALTIME, &bbf->lastwrite); + bbf->crc = stm32_bbsram_crc(bbf); + + BBSRAM_DUMP(bbf,"close done"); + return bbf->len; +} + +/**************************************************************************** + * Name: stm32_bbsram_close + * + * Description: close the device + * + ****************************************************************************/ + +static int stm32_bbsram_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct stm32_bbsram_s *bbr; + int ret = OK; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_s *)inode->i_private; + + stm32_bbsram_semtake(bbr); + + BBSRAM_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 */ + + stm32_bbsram_unlock(); + stm32_bbsram_internal_close(bbr->bbf); + stm32_bbsram_lock(); + } + } + } + + stm32_bbsram_semgive(bbr); + return ret; +} + +/**************************************************************************** + * Name: stm32_bbsram_seek + ****************************************************************************/ + +static off_t stm32_bbsram_seek(FAR struct file *filep, off_t offset, + int whence) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct stm32_bbsram_s *bbr; + off_t newpos; + int ret; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_s *)inode->i_private; + + stm32_bbsram_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 */ + + stm32_bbsram_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; + } + + stm32_bbsram_semgive(bbr); + return ret; +} + +/**************************************************************************** + * Name: stm32_bbsram_read + ****************************************************************************/ + +static ssize_t stm32_bbsram_read(FAR struct file *filep, FAR char *buffer, + size_t len) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct stm32_bbsram_s *bbr; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_s *)inode->i_private; + + stm32_bbsram_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; + stm32_bbsram_semgive(bbr); + return len; +} + +/**************************************************************************** + * Name: stm32_bbsram_internal_write + ****************************************************************************/ + +static ssize_t stm32_bbsram_internal_write(FAR struct bbsramfh_s *bbf, + FAR const char *buffer, + off_t offset, size_t len) +{ + bbf->dirty = 1; + memcpy(&bbf->data[offset], buffer, len); + return len; +} + +/**************************************************************************** + * Name: stm32_bbsram_write + ****************************************************************************/ + +static ssize_t stm32_bbsram_write(FAR struct file *filep, FAR const char *buffer, + size_t len) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct stm32_bbsram_s *bbr; + int ret = -EFBIG; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_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 */ + + stm32_bbsram_semtake(bbr); + BBSRAM_DUMP(bbr->bbf,"write"); + stm32_bbsram_unlock(); + stm32_bbsram_internal_write(bbr->bbf, buffer, filep->f_pos, len); + stm32_bbsram_lock(); + filep->f_pos += len; + BBSRAM_DUMP(bbr->bbf,"write done"); + stm32_bbsram_semgive(bbr); + } + + BBSRAM_DEBUG_READ(); + return ret; +} + +/**************************************************************************** + * Name: stm32_bbsram_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static int stm32_bbsram_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + if (setup) + { + fds->revents |= (fds->events & (POLLIN|POLLOUT)); + if (fds->revents != 0) + { + sem_post(fds->sem); + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_bbsram_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ + +static int stm32_bbsram_ioctl(FAR struct file *filep, int cmd, + unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct stm32_bbsram_s *bbr; + int ret = -ENOTTY; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_s *)inode->i_private; + + if (cmd == STM32_BBSRAM_GETDESC_IOCTL) + { + FAR struct bbsramd_s *bbrr = (FAR struct bbsramd_s *)((uintptr_t)arg); + + stm32_bbsram_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 == stm32_bbsram_crc(bbr->bbf)) ? eCRCValid : 0; + bbrr->flags = (bbr->bbf->dirty) ? eDirty : 0; + ret = OK; + } + + stm32_bbsram_semgive(bbr); + } + + return ret; +} + +/**************************************************************************** + * Name: stm32_bbsram_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 BBSRAM intact. + * It should be called called on the 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 stm32_bbsram_unlink(FAR struct inode *inode) +{ + FAR struct stm32_bbsram_s *bbr; + + DEBUGASSERT(inode && inode->i_private); + bbr = (FAR struct stm32_bbsram_s *)inode->i_private; + + stm32_bbsram_semtake(bbr); + stm32_bbsram_unlock(); + memset(bbr->bbf->data, 0, bbr->bbf->len); + bbr->bbf->lastwrite.tv_nsec = 0; + bbr->bbf->lastwrite.tv_sec = 0; + bbr->bbf->crc = stm32_bbsram_crc(bbr->bbf); + stm32_bbsram_lock(); + bbr->refs = 0; + stm32_bbsram_semgive(bbr); + sem_destroy(&bbr->exclsem); + return 0; +} +#endif + +/**************************************************************************** + * Name: stm32_bbsram_probe + * + * Description: Based on the number of files defined and their sizes + * Initializes the base pointers to the file entries. + * + ****************************************************************************/ + +static int stm32_bbsram_probe(int *ent, struct stm32_bbsram_s pdev[]) +{ + int i; + int avail = STM32_BBSRAM_SIZE; + int alloc; + int size; + int ret = -EFBIG; + struct bbsramfh_s *pf = (struct bbsramfh_s *) STM32_BKPSRAM_BASE; + + for (i = 0; (i < CONFIG_STM32_BBSRAM_FILES) && ent[i] && (avail > 0); i++) + { + /* Validate the actual allocations against what is in the BBSRAM*/ + + size = ent[i]; + + /* Use all that is left */ + + if (size == -1) + { + size = avail - (BBSRAM_HEADER_SIZE + BBSRAM_ALIGNMENT); + } + + /* Add in header size and keep aligned */ + + alloc = size + BBSRAM_HEADER_SIZE + BBSRAM_ALIGNMENT; + alloc &= ~(BBSRAM_ALIGNMENT-1); + + /* Does it fit? */ + + if (alloc <= avail) + { + ret = i + 1; + BBSRAM_DUMP(pf, "probe"); + + if (pf->len != size || + pf->fileno != i || + pf->crc != stm32_bbsram_crc(pf)) + { + + /* Not Valid so wipe the file in BBSRAM */ + + memset((uint8_t*)pf, 0, alloc); + pf->fileno = i; + pf->len = size; + pf->crc = stm32_bbsram_crc(pf); + BBSRAM_DUMP(pf,"probe reset"); + } + + pdev[i].bbf = pf; + pf = (struct bbsramfh_s *)((uint8_t *)pf + alloc); + sem_init(&g_bbsram[i].exclsem, 0, 1); + } + + avail -= alloc; + } + + BBSRAM_DEBUG_READ(); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32_bbsraminitialize + * + * Description: + * Initialize the Battery Backed up SRAM driver. + * + * 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_STM32_BBSRAM_FILES + * CONFIG_STM32_BBSRAM_FILES will be returned. + * + * Returned Value: + * Number of files created on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +int stm32_bbsraminitialize(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_bbsram, 0, sizeof(g_bbsram)); + + /* Clocking for the PWR block must be provided. However, this is done + * unconditionally in stm32f40xxx_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_STM32_BKPSRAM is defined. + */ + + /* Allow Access */ + + stm32_bbsram_unlock(); + + /* Enable backup regulator so that the data is retained in Standby and + * VBAT modes + */ + + stm32_pwr_enablebreg(true); + + fcnt = stm32_bbsram_probe(sizes, g_bbsram); + + 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, &stm32_bbsram_fops, 0666, &g_bbsram[i]); + } + + /* Disallow Access */ + + stm32_bbsram_lock(); + return ret < OK ? ret : fcnt; +} + +/**************************************************************************** +* Function: stm32_bbsram_savepanic +* +* Description: +* Saves the panic context in a previously allocated BBSRAM file +* +* Parameters: +* fileno - the value returned by the ioctl STM32_BBSRAM_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_STM32_SAVE_CRASHDUMP) +int stm32_bbsram_savepanic(int fileno, uint8_t *context, int length) +{ + FAR struct bbsramfh_s *bbf; + int fill; + + /* 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_STM32_BBSRAM_FILES); + + bbf = g_bbsram[fileno].bbf; + + DEBUGASSERT(bbf); + + if (bbf) + { + /* Clamp length if too big */ + + if (length > bbf->len) + { + length = bbf->len; + } + + stm32_bbsram_unlock(); + + stm32_bbsram_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 */ + + stm32_bbsram_internal_close(bbf); + + stm32_bbsram_lock(); + } + } + + return length; +} +#endif + +#endif /* CONFIG_BBSRAM_DRIVER */ diff --git a/arch/arm/src/stm32/stm32_bbsram.h b/arch/arm/src/stm32/stm32_bbsram.h new file mode 100644 index 0000000000..69d0046f5c --- /dev/null +++ b/arch/arm/src/stm32/stm32_bbsram.h @@ -0,0 +1,166 @@ +/**************************************************************************** + * arch/arm/src/stm32/stm32_bbsram.h + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * David Sidrane + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32_STM32_BBSRAM_H +#define __ARCH_ARM_SRC_STM32_STM32_BBSRAM_H + +/**************************************************************************** + * The purpose of this driver is to add battery backup file to the file + * system. There can be CONFIG_STM32_BBRSRAM_COUNT files defined. + * These files are of fixed size up to the maximum of the backing SRAM. + * In the care of the STM32F2 and STM32F4 this is a maximum of 4K Bytes. + * + * 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 + ****************************************************************************/ + +#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) +# define STM32_BBSRAM_SIZE 4096 +#else +# error No backup SRAM on this STM32 +#endif + +#if !defined(CONFIG_STM32_BBSRAM_FILES) +# define CONFIG_STM32_BBSRAM_FILES 4 +#endif + +/* REVISIT: What guarantees that STM32_BBSRAM_GETDESC_IOCTL has a unique + * value among all over _DIOC() values? + */ + +#define STM32_BBSRAM_GETDESC_IOCTL _DIOC(0x0010) /* Returns a bbsramd_s */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +enum bbsramdf_e +{ + eCRCValid = 1, /* The crc is valid */ + eDirty = 2, /* The file was closed */ + +}; + +struct bbsramd_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: stm32_bbsraminitialize + * + * Description: + * Initialize the Battery Backed up SRAM driver. + * + * 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_STM32_BBSRAM_FILES + * CONFIG_STM32_BBSRAM_FILES will be returned. + * + * Returned Value: + * Number of files created on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +int stm32_bbsraminitialize(char *devpath, int *sizes); + +/**************************************************************************** +* Function: stm32_bbsram_savepanic +* +* Description: +* Saves the panic context in a previously allocated BBSRAM file +* +* Parameters: +* fileno - the value returned by the ioctl STM32_BBSRAM_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_STM32_SAVE_CRASHDUMP) +int stm32_bbsram_savepanic(int fileno, uint8_t *context, int length); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32_STM32_BBSRAM_H */ diff --git a/arch/arm/src/stm32/stm32_ccm.c b/arch/arm/src/stm32/stm32_ccm.c old mode 100755 new mode 100644 diff --git a/arch/arm/src/stm32/stm32_ccm.h b/arch/arm/src/stm32/stm32_ccm.h old mode 100755 new mode 100644 diff --git a/arch/arm/src/stm32/stm32_i2c_alt.c b/arch/arm/src/stm32/stm32_i2c_alt.c old mode 100755 new mode 100644 diff --git a/arch/arm/src/stm32/stm32_sdio.c b/arch/arm/src/stm32/stm32_sdio.c old mode 100755 new mode 100644 diff --git a/arch/arm/src/stm32/stm32_usbhost.c b/arch/arm/src/stm32/stm32_usbhost.c old mode 100755 new mode 100644