diff --git a/arch/renesas/src/rx65n/Kconfig b/arch/renesas/src/rx65n/Kconfig index 269895caadb2e..e553f5f971441 100644 --- a/arch/renesas/src/rx65n/Kconfig +++ b/arch/renesas/src/rx65n/Kconfig @@ -149,7 +149,7 @@ config RX65N_CMT0 config RX65N_CMT1 bool "CMT1" default n - depends on BOARD_CRASHDUMP && RX65N_SBRAM && RX65N_SAVE_CRASHDUMP + depends on BOARD_CRASHDUMP_CUSTOM && RX65N_SBRAM && RX65N_SAVE_CRASHDUMP config RX65N_CMT2 bool "CMT2" @@ -170,7 +170,7 @@ config RX65N_IRQ_GROUP config RX65N_SBRAM bool "SBRAM" default n - depends on BOARD_CRASHDUMP + depends on BOARD_CRASHDUMP_CUSTOM config RX65N_SAVE_CRASHDUMP bool "SBRAM Save Crashdump" @@ -541,7 +541,7 @@ config RX65N_CMT0 config RX65N_CMT1 bool "CMT1" default n - depends on BOARD_CRASHDUMP && RX65N_SBRAM && RX65N_SAVE_CRASHDUMP + depends on BOARD_CRASHDUMP_CUSTOM && RX65N_SBRAM && RX65N_SAVE_CRASHDUMP config RX65N_CMT2 bool "CMT2" @@ -562,7 +562,7 @@ config RX65N_IRQ_GROUP config RX65N_SBRAM bool "SBRAM" default n - depends on BOARD_CRASHDUMP + depends on BOARD_CRASHDUMP_CUSTOM config RX65N_SAVE_CRASHDUMP bool "SBRAM Save Crashdump" diff --git a/boards/Kconfig b/boards/Kconfig index 6be3cf0f3bf10..ccaae55b2fe93 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -4693,9 +4693,9 @@ source "boards/arm/nrf91/common/Kconfig" endif endif -config BOARD_CRASHDUMP - bool "Enable Board level logging of crash dumps" - default n +choice + prompt "BOARD crashdump method" + default BOARD_CRASHDUMP_NONE ---help--- If selected up_assert will call out to board_crashdump, in the case of an assertion failure, prior to calling exit. Or in the @@ -4712,28 +4712,43 @@ config BOARD_CRASHDUMP config BOARD_COREDUMP_SYSLOG bool "Enable Core dump to syslog" - default n depends on COREDUMP ---help--- Enable put coredump to syslog when crash. config BOARD_COREDUMP_BLKDEV bool "Enable Core Dump to block device" - default n depends on COREDUMP ---help--- - Enable save coredump at block device when crash. + Enable save coredump to block device when crash. + +config BOARD_COREDUMP_MTDDEV + bool "Enable Core Dump to mtd device" + depends on COREDUMP + ---help--- + Enable save coredump to mtd device when crash. + +config BOARD_CRASHDUMP_CUSTOM + bool "Enable Core Dump with custom method" + ---help--- + Enable save coredump with custom method. only work with + board_crashdump api. + +config BOARD_CRASHDUMP_NONE + bool "No Board level crash dump" + +endchoice # BOARD crashdump method -config BOARD_COREDUMP_BLKDEV_PATH - string "Save Core Dump block device PATH" - depends on BOARD_COREDUMP_BLKDEV +config BOARD_COREDUMP_DEVPATH + string "Save Core Dump data with device PATH" + depends on BOARD_COREDUMP_BLKDEV || BOARD_COREDUMP_MTDDEV ---help--- - Save coredump file block device path. + Save coredump file into block/mtd device path. config BOARD_COREDUMP_FULL bool "Core Dump all thread registers and stacks" default y - depends on BOARD_COREDUMP_SYSLOG || BOARD_COREDUMP_BLKDEV + depends on !BOARD_CRASHDUMP_NONE ---help--- Enable to support for the dump all task registers and stacks. @@ -4741,7 +4756,7 @@ config BOARD_COREDUMP_COMPRESSION bool "Enable Core Dump compression" default y select LIBC_LZF - depends on BOARD_COREDUMP_SYSLOG || BOARD_COREDUMP_BLKDEV + depends on !BOARD_CRASHDUMP_NONE ---help--- Enable LZF compression algorithm for core dump content diff --git a/include/nuttx/board.h b/include/nuttx/board.h index 33053a2f93cd9..d3430d2b3cb64 100644 --- a/include/nuttx/board.h +++ b/include/nuttx/board.h @@ -820,7 +820,7 @@ int board_button_irq(int id, xcpt_t irqhandler, FAR void *arg); * ****************************************************************************/ -#ifdef CONFIG_BOARD_CRASHDUMP +#ifdef CONFIG_BOARD_CRASHDUMP_CUSTOM struct tcb_s; void board_crashdump(uintptr_t sp, FAR struct tcb_s *tcb, FAR const char *filename, int lineno, diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h index 5f39fab6550e7..dedf16a5f6ba9 100644 --- a/include/nuttx/streams.h +++ b/include/nuttx/streams.h @@ -293,7 +293,7 @@ struct lib_lzfoutstream_s #ifndef CONFIG_DISABLE_MOUNTPOINT struct lib_blkoutstream_s { - struct lib_outstream_s common; + struct lib_sostream_s common; FAR struct inode *inode; struct geometry geo; FAR unsigned char *cache; @@ -303,7 +303,7 @@ struct lib_blkoutstream_s #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD) struct lib_mtdoutstream_s { - struct lib_outstream_s common; + struct lib_sostream_s common; FAR struct inode *inode; struct mtd_geometry_s geo; FAR unsigned char *cache; diff --git a/libs/libc/stream/lib_blkoutstream.c b/libs/libc/stream/lib_blkoutstream.c index c9132b445da07..7ee0e793f1af8 100644 --- a/libs/libc/stream/lib_blkoutstream.c +++ b/libs/libc/stream/lib_blkoutstream.c @@ -45,7 +45,7 @@ * Name: blkoutstream_flush ****************************************************************************/ -static int blkoutstream_flush(FAR struct lib_outstream_s *self) +static int blkoutstream_flush(FAR struct lib_sostream_s *self) { FAR struct lib_blkoutstream_s *stream = (FAR struct lib_blkoutstream_s *)self; @@ -61,11 +61,81 @@ static int blkoutstream_flush(FAR struct lib_outstream_s *self) return ret; } +/**************************************************************************** + * Name: blkoutstream_seek + ****************************************************************************/ + +static off_t blkoutstream_seek(FAR struct lib_sostream_s *self, + off_t offset, int whence) +{ + FAR struct lib_blkoutstream_s *stream = + (FAR struct lib_blkoutstream_s *)self; + size_t sectorsize = stream->geo.geo_sectorsize; + off_t streamsize = sectorsize * stream->geo.geo_nsectors; + FAR struct inode *inode = stream->inode; + off_t sector; + off_t ret; + + switch (whence) + { + case SEEK_SET: + break; + case SEEK_END: + offset += streamsize; + break; + case SEEK_CUR: + offset += self->nput; + break; + default: + return -ENOTSUP; + } + + /* Seek to negative value or value larger than maximum size shall fail. */ + + if (offset < 0 || offset > streamsize) + { + return -EINVAL; + } + + if (self->nput % sectorsize) + { + sector = self->nput / sectorsize; + if (offset >= sector * sectorsize && + offset < (sector + 1) * sectorsize) + { + /* Inside same sector */ + + goto out; + } + + ret = inode->u.i_bops->write(stream->inode, stream->cache, + sector, 1); + if (ret < 0) + { + return ret; + } + } + + if (offset % sectorsize) + { + ret = inode->u.i_bops->read(inode, stream->cache, + offset / sectorsize, 1); + if (ret < 0) + { + return ret; + } + } + +out: + self->nput = offset; + return offset; +} + /**************************************************************************** * Name: blkoutstream_puts ****************************************************************************/ -static ssize_t blkoutstream_puts(FAR struct lib_outstream_s *self, +static ssize_t blkoutstream_puts(FAR struct lib_sostream_s *self, FAR const void *buf, size_t len) { FAR struct lib_blkoutstream_s *stream = @@ -140,7 +210,7 @@ static ssize_t blkoutstream_puts(FAR struct lib_outstream_s *self, * Name: blkoutstream_putc ****************************************************************************/ -static void blkoutstream_putc(FAR struct lib_outstream_s *self, int ch) +static void blkoutstream_putc(FAR struct lib_sostream_s *self, int ch) { char tmp = ch; blkoutstream_puts(self, &tmp, 1); @@ -240,6 +310,7 @@ int lib_blkoutstream_open(FAR struct lib_blkoutstream_s *stream, stream->common.putc = blkoutstream_putc; stream->common.puts = blkoutstream_puts; stream->common.flush = blkoutstream_flush; + stream->common.seek = blkoutstream_seek; return OK; } diff --git a/libs/libc/stream/lib_mtdoutstream.c b/libs/libc/stream/lib_mtdoutstream.c index 8ea4da95c825b..eebd15f3c5e3c 100644 --- a/libs/libc/stream/lib_mtdoutstream.c +++ b/libs/libc/stream/lib_mtdoutstream.c @@ -47,11 +47,11 @@ * Name: mtdoutstream_flush ****************************************************************************/ -static int mtdoutstream_flush(FAR struct lib_outstream_s *self) +static int mtdoutstream_flush(FAR struct lib_sostream_s *self) { FAR struct lib_mtdoutstream_s *stream = (FAR struct lib_mtdoutstream_s *)self; - FAR struct inode *inode = stream->inode; + FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd; size_t erasesize = stream->geo.erasesize; size_t nblkpererase = erasesize / stream->geo.blocksize; int ret = OK; @@ -60,13 +60,13 @@ static int mtdoutstream_flush(FAR struct lib_outstream_s *self) { size_t sblock = self->nput / erasesize; - ret = MTD_ERASE(inode->u.i_mtd, sblock, 1); + ret = MTD_ERASE(i_mtd, sblock, 1); if (ret < 0) { return ret; } - ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase, + ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, nblkpererase, stream->cache); } @@ -77,15 +77,15 @@ static int mtdoutstream_flush(FAR struct lib_outstream_s *self) * Name: mtdoutstream_puts ****************************************************************************/ -static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self, +static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, FAR const void *buf, size_t len) { FAR struct lib_mtdoutstream_s *stream = (FAR struct lib_mtdoutstream_s *)self; - FAR struct inode *inode = stream->inode; - FAR const unsigned char *ptr = buf; + FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd; size_t erasesize = stream->geo.erasesize; size_t nblkpererase = erasesize / stream->geo.blocksize; + FAR const unsigned char *ptr = buf; size_t remain = len; ssize_t ret; @@ -113,14 +113,14 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self, if (offset == erasesize) { - ret = MTD_ERASE(inode->u.i_mtd, sblock, 1); + ret = MTD_ERASE(i_mtd, sblock, 1); if (ret < 0) { return ret; } - ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase, - nblkpererase, stream->cache); + ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, + nblkpererase, stream->cache); if (ret < 0) { return ret; @@ -129,8 +129,8 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self, } else if (remain < erasesize) { - ret = MTD_READ(stream->inode->u.i_mtd, sblock * erasesize, - erasesize, stream->cache); + ret = MTD_BREAD(i_mtd, sblock * nblkpererase, + nblkpererase, stream->cache); if (ret < 0) { return ret; @@ -145,14 +145,14 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self, size_t nblock = remain / erasesize; size_t copyin = nblock * erasesize; - ret = MTD_ERASE(inode->u.i_mtd, sblock, nblock); + ret = MTD_ERASE(i_mtd, sblock, nblock); if (ret < 0) { return ret; } - ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase, - nblock * nblkpererase, ptr); + ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, + nblock * nblkpererase, ptr); if (ret < 0) { return ret; @@ -171,12 +171,91 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self, * Name: mtdoutstream_putc ****************************************************************************/ -static void mtdoutstream_putc(FAR struct lib_outstream_s *self, int ch) +static void mtdoutstream_putc(FAR struct lib_sostream_s *self, int ch) { char tmp = ch; mtdoutstream_puts(self, &tmp, 1); } +/**************************************************************************** + * Name: mtdoutstream_seek + ****************************************************************************/ + +static off_t mtdoutstream_seek(FAR struct lib_sostream_s *self, + off_t offset, int whence) +{ + FAR struct lib_mtdoutstream_s *stream = + (FAR struct lib_mtdoutstream_s *)self; + FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd; + size_t erasesize = stream->geo.erasesize; + off_t streamsize = erasesize * stream->geo.neraseblocks; + size_t nblkpererase = erasesize / stream->geo.blocksize; + size_t block; + off_t ret; + + switch (whence) + { + case SEEK_SET: + break; + case SEEK_END: + offset += streamsize; + break; + case SEEK_CUR: + offset += self->nput; + break; + default: + return -ENOTSUP; + } + + /* Seek to negative value or value larger than maximum size shall fail */ + + if (offset < 0 || offset > streamsize) + { + return -EINVAL; + } + + if (self->nput % erasesize) + { + block = self->nput / erasesize; + if (offset >= block * erasesize && + offset < (block + 1) * erasesize) + { + /* Inside same erase block */ + + goto out; + } + + ret = MTD_ERASE(i_mtd, block, 1); + if (ret < 0) + { + return ret; + } + + ret = MTD_BWRITE(i_mtd, block * nblkpererase, + nblkpererase, stream->cache); + if (ret < 0) + { + return ret; + } + } + + if (offset % erasesize) + { + block = offset / erasesize; + + ret = MTD_BREAD(i_mtd, block * nblkpererase, + nblkpererase, stream->cache); + if (ret < 0) + { + return ret; + } + } + +out: + self->nput = offset; + return offset; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -274,6 +353,7 @@ int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream, stream->common.putc = mtdoutstream_putc; stream->common.puts = mtdoutstream_puts; stream->common.flush = mtdoutstream_flush; + stream->common.seek = mtdoutstream_seek; return OK; } diff --git a/sched/init/nx_bringup.c b/sched/init/nx_bringup.c index 2ea82b920ad33..f9dbb69d350e0 100644 --- a/sched/init/nx_bringup.c +++ b/sched/init/nx_bringup.c @@ -322,8 +322,7 @@ static inline void nx_start_application(void) board_late_initialize(); #endif -#if defined(CONFIG_BOARD_COREDUMP_SYSLOG) || \ - defined(CONFIG_BOARD_COREDUMP_BLKDEV) +#ifndef CONFIG_BOARD_CRASHDUMP_NONE coredump_initialize(); #endif diff --git a/sched/misc/assert.c b/sched/misc/assert.c index f07bad20f0614..b23072c59ab3e 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -765,17 +765,14 @@ static void dump_fatal_info(FAR struct tcb_s *rtcb, usbtrace_enumerate(assert_tracecallback, NULL); #endif -#ifdef CONFIG_BOARD_CRASHDUMP - board_crashdump(up_getsp(), rtcb, filename, linenum, msg, regs); -#endif - -#if defined(CONFIG_BOARD_COREDUMP_SYSLOG) || \ - defined(CONFIG_BOARD_COREDUMP_BLKDEV) - /* Flush previous SYSLOG data before possible long time coredump */ syslog_flush(); +#ifdef CONFIG_BOARD_CRASHDUMP_CUSTOM + board_crashdump(up_getsp(), rtcb, filename, linenum, msg, regs); +#elif !defined(CONFIG_BOARD_CRASHDUMP_NONE) + /* Dump core information */ # ifdef CONFIG_BOARD_COREDUMP_FULL diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index 1de2fb5f2b6c6..9d00b080a33ef 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -47,6 +47,11 @@ # define ELF_PAGESIZE 1024 #endif +#if defined(CONFIG_BOARD_COREDUMP_BLKDEV) || \ + defined(CONFIG_BOARD_COREDUMP_MTDDEV) +# define CONFIG_BOARD_COREDUMP_DEV +#endif + #define PROGRAM_ALIGNMENT 64 #define ROUNDUP(x, y) ((x + (y - 1)) / (y)) * (y) @@ -87,8 +92,9 @@ static struct lib_hexdumpstream_s g_hexstream; #endif #ifdef CONFIG_BOARD_COREDUMP_BLKDEV -static struct lib_blkoutstream_s g_blockstream; -static unsigned char *g_blockinfo; +static struct lib_blkoutstream_s g_devstream; +#elif defined(CONFIG_BOARD_COREDUMP_MTDDEV) +static struct lib_mtdoutstream_s g_devstream; #endif #ifdef CONFIG_BOARD_MEMORY_RANGE @@ -670,77 +676,73 @@ static void coredump_dump_syslog(pid_t pid) #endif /**************************************************************************** - * Name: coredump_dump_blkdev + * Name: coredump_dump_dev * * Description: - * Save coredump to block device. + * Save coredump to storage device. * ****************************************************************************/ -#ifdef CONFIG_BOARD_COREDUMP_BLKDEV -static void coredump_dump_blkdev(pid_t pid) +#ifdef CONFIG_BOARD_COREDUMP_DEV +static void coredump_dump_dev(pid_t pid) { - FAR void *stream = &g_blockstream; - FAR struct coredump_info_s *info; - blkcnt_t nsectors; + FAR void *stream = &g_devstream; + struct coredump_info_s info; int ret; - if (g_blockstream.inode == NULL) + if (g_devstream.inode == NULL) { _alert("Coredump device not found\n"); return; } - nsectors = (sizeof(struct coredump_info_s) + - g_blockstream.geo.geo_sectorsize - 1) / - g_blockstream.geo.geo_sectorsize; - - ret = g_blockstream.inode->u.i_bops->read(g_blockstream.inode, - g_blockinfo, g_blockstream.geo.geo_nsectors - nsectors, nsectors); +#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION + lib_lzfoutstream(&g_lzfstream, stream); + stream = &g_lzfstream; +#endif + ret = coredump(g_regions, stream, pid); if (ret < 0) { - _alert("Coredump information read fail\n"); + _alert("Coredump fail %d\n", ret); return; } - info = (FAR struct coredump_info_s *)g_blockinfo; - -#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION - lib_lzfoutstream(&g_lzfstream, - (FAR struct lib_outstream_s *)&g_blockstream); - stream = &g_lzfstream; -#endif + info.magic = COREDUMP_MAGIC; + info.size = g_devstream.common.nput; + clock_gettime(CLOCK_REALTIME, &info.time); + uname(&info.name); - ret = coredump(g_regions, stream, pid); + ret = lib_stream_seek(&g_devstream, -(off_t)sizeof(info), SEEK_END); if (ret < 0) { - _alert("Coredump fail\n"); + _alert("Coredump info seek fail %d\n", ret); return; } - info->magic = COREDUMP_MAGIC; - info->size = g_blockstream.common.nput; - clock_gettime(CLOCK_REALTIME, &info->time); - uname(&info->name); - ret = g_blockstream.inode->u.i_bops->write(g_blockstream.inode, - (FAR void *)info, g_blockstream.geo.geo_nsectors - nsectors, nsectors); + if (info.size > ret) + { + _alert("Coredump no enough space for info\n"); + return; + } + + ret = lib_stream_puts(&g_devstream, &info, sizeof(info)); if (ret < 0) { - _alert("Coredump information write fail\n"); + _alert("Coredump information write fail %d\n", ret); return; } - /* Close block device directly, make sure all data write to block device */ + /* Flush to ensure outstream write all data to storage device */ - ret = g_blockstream.inode->u.i_bops->close(g_blockstream.inode); + ret = lib_stream_flush(&g_devstream); if (ret < 0) { - _alert("Coredump information close fail\n"); + _alert("Coredump flush fail %d\n", ret); return; } - _alert("Finish coredump, write %d bytes to %s\n", - info->size, CONFIG_BOARD_COREDUMP_BLKDEV_PATH); + _alert("Finish coredump, write %zu bytes to %s\n", + info.size, CONFIG_BOARD_COREDUMP_DEVPATH); } #endif @@ -859,7 +861,6 @@ int coredump_add_memory_region(FAR const void *ptr, size_t size, int coredump_initialize(void) { - blkcnt_t nsectors; int ret = 0; #ifdef CONFIG_BOARD_MEMORY_RANGE @@ -867,29 +868,21 @@ int coredump_initialize(void) #endif #ifdef CONFIG_BOARD_COREDUMP_BLKDEV - ret = lib_blkoutstream_open(&g_blockstream, - CONFIG_BOARD_COREDUMP_BLKDEV_PATH); - if (ret < 0) - { - _alert("%s Coredump device not found\n", - CONFIG_BOARD_COREDUMP_BLKDEV_PATH); - return ret; - } - - nsectors = (sizeof(struct coredump_info_s) + - g_blockstream.geo.geo_sectorsize - 1) / - g_blockstream.geo.geo_sectorsize; + ret = lib_blkoutstream_open(&g_devstream, + CONFIG_BOARD_COREDUMP_DEVPATH); +#elif defined(CONFIG_BOARD_COREDUMP_MTDDEV) + ret = lib_mtdoutstream_open(&g_devstream, + CONFIG_BOARD_COREDUMP_DEVPATH); +#endif - g_blockinfo = kmm_malloc(g_blockstream.geo.geo_sectorsize * nsectors); - if (g_blockinfo == NULL) +#ifdef CONFIG_BOARD_COREDUMP_DEV + if (ret < 0) { - _alert("Coredump device memory alloc fail\n"); - lib_blkoutstream_close(&g_blockstream); - return -ENOMEM; + _alert("%s Coredump device not found %d\n", + CONFIG_BOARD_COREDUMP_DEVPATH, ret); } #endif - UNUSED(nsectors); return ret; } @@ -910,8 +903,8 @@ void coredump_dump(pid_t pid) coredump_dump_syslog(pid); #endif -#ifdef CONFIG_BOARD_COREDUMP_BLKDEV - coredump_dump_blkdev(pid); +#ifdef CONFIG_BOARD_COREDUMP_DEV + coredump_dump_dev(pid); #endif }