summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-05-03 12:52:33 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-05-03 12:52:33 -0600
commit1092e4b16395d945517b9bcbc2c48828fbe9303c (patch)
treee2171ab3f21ae1e0610903694901c776a7e1a1d8
parent2567deb0338a774086231fbb778b639c10398cc1 (diff)
downloadnuttx-1092e4b16395d945517b9bcbc2c48828fbe9303c.tar.gz
nuttx-1092e4b16395d945517b9bcbc2c48828fbe9303c.tar.bz2
nuttx-1092e4b16395d945517b9bcbc2c48828fbe9303c.zip
Rearchitecting of some MTD, partition, SMART interfaces, and FLASH drivers to: Better use the byte write capbility when available and to use smaller erase sectors for the erase sector size when available).
-rw-r--r--apps/ChangeLog.txt2
-rw-r--r--apps/examples/Kconfig1
-rw-r--r--apps/examples/Make.defs4
-rw-r--r--apps/examples/Makefile6
-rw-r--r--apps/examples/README.txt28
-rw-r--r--apps/examples/mtdpart/Kconfig6
-rw-r--r--apps/examples/smart/.gitignore12
-rw-r--r--apps/examples/smart/Kconfig71
-rw-r--r--apps/examples/smart/Makefile96
-rw-r--r--apps/examples/smart/smart_main.c954
-rw-r--r--apps/examples/smart_test/smart_test.c2
-rw-r--r--nuttx/ChangeLog8
-rw-r--r--nuttx/Documentation/NuttX.html45
-rw-r--r--nuttx/configs/mikroe-stm32f4/Kconfig69
-rw-r--r--nuttx/configs/mikroe-stm32f4/README.txt15
-rw-r--r--nuttx/configs/mikroe-stm32f4/src/up_nsh.c82
-rw-r--r--nuttx/configs/mikroe-stm32f4/usbnsh/defconfig67
-rw-r--r--nuttx/configs/stm32f4discovery/README.txt15
-rw-r--r--nuttx/drivers/mtd/Kconfig27
-rw-r--r--nuttx/drivers/mtd/m25px.c330
-rw-r--r--nuttx/drivers/mtd/mtd_partition.c11
-rw-r--r--nuttx/drivers/mtd/rammtd.c55
-rw-r--r--nuttx/drivers/mtd/smart.c313
-rw-r--r--nuttx/fs/smartfs/smartfs_smart.c9
-rw-r--r--nuttx/fs/smartfs/smartfs_utils.c22
-rw-r--r--nuttx/include/nuttx/fs/ioctl.h9
-rw-r--r--nuttx/include/nuttx/mtd.h13
-rw-r--r--nuttx/tools/kconfig2html.c3
28 files changed, 1819 insertions, 456 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 753bdc5cc..d6971dc45 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -546,3 +546,5 @@
the SMART block driver and file system (Ken Pettit, 2013-5-1).
* apps/examples/mtdpart: Extended to the test. The original test
coverage was superficial (2013-5-3).
+ * apps/examples/smart: This is an adaptation of the NXFFS stress
+ test for the SMART file system (Ken Pettit, 2013-5-3).
diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig
index b1c7e7793..11a56a81c 100644
--- a/apps/examples/Kconfig
+++ b/apps/examples/Kconfig
@@ -49,6 +49,7 @@ source "$APPSDIR/examples/sendmail/Kconfig"
source "$APPSDIR/examples/serloop/Kconfig"
source "$APPSDIR/examples/flash_test/Kconfig"
source "$APPSDIR/examples/smart_test/Kconfig"
+source "$APPSDIR/examples/smart/Kconfig"
source "$APPSDIR/examples/telnetd/Kconfig"
source "$APPSDIR/examples/thttpd/Kconfig"
source "$APPSDIR/examples/tiff/Kconfig"
diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs
index eb2b5ed87..67b07a21b 100644
--- a/apps/examples/Make.defs
+++ b/apps/examples/Make.defs
@@ -222,6 +222,10 @@ ifeq ($(CONFIG_EXAMPLES_SMART_TEST),y)
CONFIGURED_APPS += examples/smart_test
endif
+ifeq ($(CONFIG_EXAMPLES_SMART),y)
+CONFIGURED_APPS += examples/smart
+endif
+
ifeq ($(CONFIG_EXAMPLES_TELNETD),y)
CONFIGURED_APPS += examples/telnetd
endif
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index 41593b8f9..a10fef5dc 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -33,7 +33,7 @@
#
############################################################################
--include $(TOPDIR)/.config # Current configuration
+-include $(TOPDIR)/.config # Current configuration
# Sub-directories
@@ -42,8 +42,8 @@ SUBDIRS += flash_test ftpc ftpd hello helloxx hidkbd igmp json keypadtest
SUBDIRS += lcdrw mm modbus mount mtdpart nettest nsh null nx nxconsole nxffs
SUBDIRS += nxflat nxhello nximage nxlines nxtext ostest pashello pipe poll
SUBDIRS += posix_spawn pwm qencoder relays rgmp romfs sendmail serloop
-SUBDIRS += smart_test telnetd thttpd tiff touchscreen udp uip usbserial
-SUBDIRS += usbstorage usbterm watchdog wget wgetjson xmlrpc
+SUBDIRS += smart smart_test telnetd thttpd tiff touchscreen udp uip
+SUBDIRS += usbserial usbstorage usbterm watchdog wget wgetjson xmlrpc
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index ec9685f4e..24afaf699 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -1463,6 +1463,34 @@ examples/serloop
Use C buffered I/O (getchar/putchar) vs. raw console I/O
(read/read).
+examples/smart
+^^^^^^^^^^^^^^
+
+ This is a test of the SMART file systemt that derives from
+ examples/nxffs.
+
+ * CONFIG_EXAMPLES_SMART: -Enable the SMART file system example
+ * CONFIG_EXAMPLES_SMART_ARCHINIT: The default is to use the RAM MTD
+ device at drivers/mtd/rammtd.c. But an architecture-specific MTD
+ driver can be used instead by defining CONFIG_EXAMPLES_SMART_ARCHINIT. In
+ this case, the initialization logic will call smart_archinitialize()
+ to obtain the MTD driver instance.
+ * CONFIG_EXAMPLES_SMART_NEBLOCKS: When CONFIG_EXAMPLES_SMART_ARCHINIT is not
+ defined, this test will use the RAM MTD device at drivers/mtd/rammtd.c
+ to simulate FLASH. In this case, this value must be provided to give
+ the nubmer of erase blocks in MTD RAM device. The size of the allocated
+ RAM drive will be: CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_SMART_NEBLOCKS
+ * CONFIG_EXAMPLES_SMART_MAXNAME: Determines the maximum size of names used
+ in the filesystem
+ * CONFIG_EXAMPLES_SMART_MAXFILE: Determines the maximum size of a file
+ * CONFIG_EXAMPLES_SMART_MAXIO: Max I/O, default 347.
+ * CONFIG_EXAMPLES_SMART_MAXOPEN: Max open files.
+ * CONFIG_EXAMPLES_SMART_MOUNTPT: SMART mountpoint
+ * CONFIG_EXAMPLES_SMART_NLOOPS: Number of test loops. default 100
+ * CONFIG_EXAMPLES_SMART_VERBOSE: Verbose output
+
+endif
+
examples/smart_test
^^^^^^^^^^^^^^^^^^^
diff --git a/apps/examples/mtdpart/Kconfig b/apps/examples/mtdpart/Kconfig
index 363b6091f..6f8e6e490 100644
--- a/apps/examples/mtdpart/Kconfig
+++ b/apps/examples/mtdpart/Kconfig
@@ -6,8 +6,12 @@
config EXAMPLES_MTDPART
bool "MTD partition test"
default n
+ depends on MTD_PARTITION && !NUTTX_KERNEL
---help---
- Enable the MTD partition test example
+ Enable the MTD partition test example.
+
+ NOTE: This example uses some internal NuttX interfaces and, hence,
+ is not available in the kernel build.
if EXAMPLES_MTDPART
diff --git a/apps/examples/smart/.gitignore b/apps/examples/smart/.gitignore
new file mode 100644
index 000000000..3c8fd3435
--- /dev/null
+++ b/apps/examples/smart/.gitignore
@@ -0,0 +1,12 @@
+Make.dep
+.depend
+.built
+*.swp
+*.asm
+*.rel
+*.lst
+*.sym
+*.adb
+*.lib
+*.src
+
diff --git a/apps/examples/smart/Kconfig b/apps/examples/smart/Kconfig
new file mode 100644
index 000000000..933b33913
--- /dev/null
+++ b/apps/examples/smart/Kconfig
@@ -0,0 +1,71 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config EXAMPLES_SMART
+ bool "SMART file system example"
+ default n
+ ---help---
+ Enable the SMART file system example
+
+if EXAMPLES_SMART
+
+config EXAMPLES_SMART_ARCHINIT
+ bool "Architecture-specific initialization"
+ default n
+ ---help---
+ The default is to use the RAM MTD device at drivers/mtd/rammtd.c.
+ But an architecture-specific MTD driver can be used instead by
+ defining EXAMPLES_SMART_ARCHINIT. In this case, the
+ initialization logic will call smart_archinitialize() to obtain
+ the MTD driver instance.
+
+config EXAMPLES_SMART_NEBLOCKS
+ int "Number of erase blocks (simulated)"
+ default 32
+ depends on !EXAMPLES_SMART_ARCHINIT
+ ---help---
+ When EXAMPLES_SMART_ARCHINIT is not defined, this test will use
+ the RAM MTD device at drivers/mtd/rammtd.c to simulate FLASH. In
+ this case, this value must be provided to give the nubmer of erase
+ blocks in MTD RAM device.
+
+ The size of the allocated RAM drive will be:
+
+ RAMMTD_ERASESIZE * EXAMPLES_SMART_NEBLOCKS
+
+config EXAMPLES_SMART_MAXNAME
+ int "Max name size"
+ default 32
+ range 1 255
+ ---help---
+ Determines the maximum size of names used in the filesystem
+
+config EXAMPLES_SMART_MAXFILE
+ int "Max file size"
+ default 8192
+ ---help---
+ Determines the maximum size of a file
+
+config EXAMPLES_SMART_MAXIO
+ int "Max I/O"
+ default 347
+
+config EXAMPLES_SMART_MAXOPEN
+ int "Max open files"
+ default 512
+
+config EXAMPLES_SMART_MOUNTPT
+ string "SMART mountpoint"
+ default "/mnt/nxffs"
+
+config EXAMPLES_SMART_NLOOPS
+ int "Number of test loops"
+ default 100
+
+config EXAMPLES_SMART_VERBOSE
+ bool "Verbose output"
+ default n
+
+endif
diff --git a/apps/examples/smart/Makefile b/apps/examples/smart/Makefile
new file mode 100644
index 000000000..60614ca5d
--- /dev/null
+++ b/apps/examples/smart/Makefile
@@ -0,0 +1,96 @@
+############################################################################
+# apps/examples/smart/Makefile
+#
+# Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# 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.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# SMART file system stress test
+
+ASRCS =
+CSRCS = smart_main.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ BIN = ..\..\libapps$(LIBEXT)
+else
+ifeq ($(WINTOOL),y)
+ BIN = ..\\..\\libapps$(LIBEXT)
+else
+ BIN = ../../libapps$(LIBEXT)
+endif
+endif
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ $(call ARCHIVE, $(BIN), $(OBJS))
+ @touch .built
+
+context:
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ $(call DELFILE, .built)
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, Make.dep)
+ $(call DELFILE, .depend)
+
+-include Make.dep
diff --git a/apps/examples/smart/smart_main.c b/apps/examples/smart/smart_main.c
new file mode 100644
index 000000000..ce303caa7
--- /dev/null
+++ b/apps/examples/smart/smart_main.c
@@ -0,0 +1,954 @@
+/****************************************************************************
+ * examples/smart/smart_main.c
+ *
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/mount.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <crc32.h>
+#include <debug.h>
+
+#include <nuttx/mtd.h>
+#include <nuttx/smart.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/fs/mksmartfs.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+/* The default is to use the RAM MTD device at drivers/mtd/rammtd.c. But
+ * an architecture-specific MTD driver can be used instead by defining
+ * CONFIG_EXAMPLES_SMART_ARCHINIT. In this case, the initialization logic
+ * will call smart_archinitialize() to obtain the MTD driver instance.
+ */
+
+#ifndef CONFIG_EXAMPLES_SMART_ARCHINIT
+
+/* This must exactly match the default configuration in drivers/mtd/rammtd.c */
+
+# ifndef CONFIG_RAMMTD_ERASESIZE
+# define CONFIG_RAMMTD_ERASESIZE 4096
+# endif
+
+# ifndef CONFIG_EXAMPLES_SMART_NEBLOCKS
+# define CONFIG_EXAMPLES_SMART_NEBLOCKS (256)
+# endif
+
+# define EXAMPLES_SMART_BUFSIZE \
+ (CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_SMART_NEBLOCKS)
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_MAXNAME
+# define CONFIG_EXAMPLES_SMART_MAXNAME 128
+#endif
+
+#if CONFIG_EXAMPLES_SMART_MAXNAME > 255
+# undef CONFIG_EXAMPLES_SMART_MAXNAME
+# define CONFIG_EXAMPLES_SMART_MAXNAME 255
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_MAXFILE
+# define CONFIG_EXAMPLES_SMART_MAXFILE 8192
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_MAXIO
+# define CONFIG_EXAMPLES_SMART_MAXIO 347
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_MAXOPEN
+# define CONFIG_EXAMPLES_SMART_MAXOPEN 512
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_MOUNTPT
+# define CONFIG_EXAMPLES_SMART_MOUNTPT "/mnt/smart"
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_NLOOPS
+# define CONFIG_EXAMPLES_SMART_NLOOPS 100
+#endif
+
+#ifndef CONFIG_EXAMPLES_SMART_VERBOSE
+# define CONFIG_EXAMPLES_SMART_VERBOSE 0
+#endif
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS)
+# define message syslog
+# define msgflush()
+#else
+# define message printf
+# define msgflush() fflush(stdout);
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct smart_filedesc_s
+{
+ FAR char *name;
+ bool deleted;
+ size_t len;
+ uint32_t crc;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+/* Pre-allocated simulated flash */
+
+#ifndef CONFIG_EXAMPLES_SMART_ARCHINIT
+static uint8_t g_simflash[EXAMPLES_SMART_BUFSIZE];
+#endif
+
+static uint8_t g_fileimage[CONFIG_EXAMPLES_SMART_MAXFILE];
+static struct smart_filedesc_s g_files[CONFIG_EXAMPLES_SMART_MAXOPEN];
+static const char g_mountdir[] = CONFIG_EXAMPLES_SMART_MOUNTPT "/";
+static int g_nfiles;
+static int g_ndeleted;
+
+static struct mallinfo g_mmbefore;
+static struct mallinfo g_mmprevious;
+static struct mallinfo g_mmafter;
+
+/****************************************************************************
+ * External Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_EXAMPLES_SMART_ARCHINIT
+extern FAR struct mtd_dev_s *smart_archinitialize(void);
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: smart_memusage
+ ****************************************************************************/
+
+static void smart_showmemusage(struct mallinfo *mmbefore,
+ struct mallinfo *mmafter)
+{
+ message("VARIABLE BEFORE AFTER\n");
+ message("======== ======== ========\n");
+ message("arena %8x %8x\n", mmbefore->arena, mmafter->arena);
+ message("ordblks %8d %8d\n", mmbefore->ordblks, mmafter->ordblks);
+ message("mxordblk %8x %8x\n", mmbefore->mxordblk, mmafter->mxordblk);
+ message("uordblks %8x %8x\n", mmbefore->uordblks, mmafter->uordblks);
+ message("fordblks %8x %8x\n", mmbefore->fordblks, mmafter->fordblks);
+}
+
+/****************************************************************************
+ * Name: smart_loopmemusage
+ ****************************************************************************/
+
+static void smart_loopmemusage(void)
+{
+ /* Get the current memory usage */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmafter = mallinfo();
+#else
+ (void)mallinfo(&g_mmafter);
+#endif
+
+ /* Show the change from the previous loop */
+
+ message("\nEnd of loop memory usage:\n");
+ smart_showmemusage(&g_mmprevious, &g_mmafter);
+
+ /* Set up for the next test */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmprevious = g_mmafter;
+#else
+ memcpy(&g_mmprevious, &g_mmafter, sizeof(struct mallinfo));
+#endif
+}
+
+/****************************************************************************
+ * Name: smart_endmemusage
+ ****************************************************************************/
+
+static void smart_endmemusage(void)
+{
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmafter = mallinfo();
+#else
+ (void)mallinfo(&g_mmafter);
+#endif
+ message("\nFinal memory usage:\n");
+ smart_showmemusage(&g_mmbefore, &g_mmafter);
+}
+
+/****************************************************************************
+ * Name: smart_randchar
+ ****************************************************************************/
+
+static inline char smart_randchar(void)
+{
+ int value = rand() % 63;
+ if (value == 0)
+ {
+ return '0';
+ }
+ else if (value <= 10)
+ {
+ return value + '0' - 1;
+ }
+ else if (value <= 36)
+ {
+ return value + 'a' - 11;
+ }
+ else /* if (value <= 62) */
+ {
+ return value + 'A' - 37;
+ }
+}
+
+/****************************************************************************
+ * Name: smart_randname
+ ****************************************************************************/
+
+static inline void smart_randname(FAR struct smart_filedesc_s *file)
+{
+ int dirlen;
+ int maxname;
+ int namelen;
+ int alloclen;
+ int i;
+
+ dirlen = strlen(g_mountdir);
+ maxname = CONFIG_EXAMPLES_SMART_MAXNAME - dirlen;
+ namelen = (rand() % maxname) + 1;
+ alloclen = namelen + dirlen;
+
+ file->name = (FAR char*)malloc(alloclen + 1);
+ if (!file->name)
+ {
+ message("ERROR: Failed to allocate name, length=%d\n", namelen);
+ msgflush();
+ exit(5);
+ }
+
+ memcpy(file->name, g_mountdir, dirlen);
+ for (i = dirlen; i < alloclen; i++)
+ {
+ file->name[i] = smart_randchar();
+ }
+
+ file->name[alloclen] = '\0';
+}
+
+/****************************************************************************
+ * Name: smart_randfile
+ ****************************************************************************/
+
+static inline void smart_randfile(FAR struct smart_filedesc_s *file)
+{
+ int i;
+
+ file->len = (rand() % CONFIG_EXAMPLES_SMART_MAXFILE) + 1;
+ for (i = 0; i < file->len; i++)
+ {
+ g_fileimage[i] = smart_randchar();
+ }
+
+ file->crc = crc32(g_fileimage, file->len);
+}
+
+/****************************************************************************
+ * Name: smart_freefile
+ ****************************************************************************/
+
+static void smart_freefile(FAR struct smart_filedesc_s *file)
+{
+ if (file->name)
+ {
+ free(file->name);
+ }
+
+ memset(file, 0, sizeof(struct smart_filedesc_s));
+}
+
+/****************************************************************************
+ * Name: smart_wrfile
+ ****************************************************************************/
+
+static inline int smart_wrfile(FAR struct smart_filedesc_s *file)
+{
+ size_t offset;
+ int fd;
+ int ret;
+
+ /* Create a random file */
+
+ smart_randname(file);
+ smart_randfile(file);
+ fd = open(file->name, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ if (fd < 0)
+ {
+ /* If it failed because there is no space on the device, then don't
+ * complain.
+ */
+
+ if (errno != ENOSPC)
+ {
+ message("ERROR: Failed to open file for writing: %d\n", errno);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ }
+
+ smart_freefile(file);
+ return ERROR;
+ }
+
+ /* Write a random amount of data to the file */
+
+ for (offset = 0; offset < file->len; )
+ {
+ size_t maxio = (rand() % CONFIG_EXAMPLES_SMART_MAXIO) + 1;
+ size_t nbytestowrite = file->len - offset;
+ ssize_t nbyteswritten;
+
+ if (nbytestowrite > maxio)
+ {
+ nbytestowrite = maxio;
+ }
+
+ nbyteswritten = write(fd, &g_fileimage[offset], nbytestowrite);
+ if (nbyteswritten < 0)
+ {
+ int err = errno;
+
+ /* If the write failed because there is no space on the device,
+ * then don't complain.
+ */
+
+ if (err != ENOSPC)
+ {
+ message("ERROR: Failed to write file: %d\n", err);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Write offset: %d\n", offset);
+ message(" Write size: %d\n", nbytestowrite);
+ ret = ERROR;
+ }
+ close(fd);
+
+ /* Remove any garbage file that might have been left behind */
+
+ ret = unlink(file->name);
+ if (ret < 0)
+ {
+ message(" Failed to remove partial file\n");
+ }
+ else
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message(" Successfully removed partial file\n");
+#endif
+ }
+
+ smart_freefile(file);
+ return ERROR;
+ }
+ else if (nbyteswritten != nbytestowrite)
+ {
+ message("ERROR: Partial write:\n");
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Write offset: %d\n", offset);
+ message(" Write size: %d\n", nbytestowrite);
+ message(" Written: %d\n", nbyteswritten);
+ }
+
+ offset += nbyteswritten;
+ }
+
+ close(fd);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: smart_fillfs
+ ****************************************************************************/
+
+static int smart_fillfs(void)
+{
+ FAR struct smart_filedesc_s *file;
+ int ret;
+ int i;
+
+ /* Create a file for each unused file structure */
+
+ for (i = 0; i < CONFIG_EXAMPLES_SMART_MAXOPEN; i++)
+ {
+ file = &g_files[i];
+ if (file->name == NULL)
+ {
+ ret = smart_wrfile(file);
+ if (ret < 0)
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message("ERROR: Failed to write file %d\n", i);
+#endif
+ return ERROR;
+ }
+
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message(" Created file %s\n", file->name);
+#endif
+ g_nfiles++;
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: smart_rdblock
+ ****************************************************************************/
+
+static ssize_t smart_rdblock(int fd, FAR struct smart_filedesc_s *file,
+ size_t offset, size_t len)
+{
+ size_t maxio = (rand() % CONFIG_EXAMPLES_SMART_MAXIO) + 1;
+ ssize_t nbytesread;
+
+ if (len > maxio)
+ {
+ len = maxio;
+ }
+
+ nbytesread = read(fd, &g_fileimage[offset], len);
+ if (nbytesread < 0)
+ {
+ message("ERROR: Failed to read file: %d\n", errno);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Read offset: %d\n", offset);
+ message(" Read size: %d\n", len);
+ return ERROR;
+ }
+ else if (nbytesread == 0)
+ {
+#if 0 /* No... we do this on purpose sometimes */
+ message("ERROR: Unexpected end-of-file:\n");
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Read offset: %d\n", offset);
+ message(" Read size: %d\n", len);
+#endif
+ return ERROR;
+ }
+ else if (nbytesread != len)
+ {
+ message("ERROR: Partial read:\n");
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Read offset: %d\n", offset);
+ message(" Read size: %d\n", len);
+ message(" Bytes read: %d\n", nbytesread);
+ }
+
+ return nbytesread;
+}
+
+/****************************************************************************
+ * Name: smart_rdfile
+ ****************************************************************************/
+
+static inline int smart_rdfile(FAR struct smart_filedesc_s *file)
+{
+ size_t ntotalread;
+ ssize_t nbytesread;
+ uint32_t crc;
+ int fd;
+
+ /* Open the file for reading */
+
+ fd = open(file->name, O_RDONLY);
+ if (fd < 0)
+ {
+ if (!file->deleted)
+ {
+ message("ERROR: Failed to open file for reading: %d\n", errno);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ }
+
+ return ERROR;
+ }
+
+ /* Read all of the data info the fileimage buffer using random read sizes */
+
+ for (ntotalread = 0; ntotalread < file->len; )
+ {
+ nbytesread = smart_rdblock(fd, file, ntotalread, file->len - ntotalread);
+ if (nbytesread < 0)
+ {
+ close(fd);
+ return ERROR;
+ }
+
+ ntotalread += nbytesread;
+ }
+
+ /* Verify the file image CRC */
+
+ crc = crc32(g_fileimage, file->len);
+ if (crc != file->crc)
+ {
+ message("ERROR: Bad CRC: %d vs %d\n", crc, file->crc);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ close(fd);
+ return ERROR;
+ }
+
+ /* Try reading past the end of the file */
+
+ nbytesread = smart_rdblock(fd, file, ntotalread, 1024) ;
+ if (nbytesread > 0)
+ {
+ message("ERROR: Read past the end of file\n");
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" Bytes read: %d\n", nbytesread);
+ close(fd);
+ return ERROR;
+ }
+
+ close(fd);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: smart_verifyfs
+ ****************************************************************************/
+
+static int smart_verifyfs(void)
+{
+ FAR struct smart_filedesc_s *file;
+ int ret;
+ int i;
+
+ /* Create a file for each unused file structure */
+
+ for (i = 0; i < CONFIG_EXAMPLES_SMART_MAXOPEN; i++)
+ {
+ file = &g_files[i];
+ if (file->name != NULL)
+ {
+ ret = smart_rdfile(file);
+ if (ret < 0)
+ {
+ if (file->deleted)
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message("Deleted file %d OK\n", i);
+#endif
+ smart_freefile(file);
+ g_ndeleted--;
+ g_nfiles--;
+ }
+ else
+ {
+ message("ERROR: Failed to read a file: %d\n", i);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ return ERROR;
+ }
+ }
+ else
+ {
+ if (file->deleted)
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message("Succesffully read a deleted file\n");
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+#endif
+ smart_freefile(file);
+ g_ndeleted--;
+ g_nfiles--;
+ return ERROR;
+ }
+ else
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message(" Verifed file %s\n", file->name);
+#endif
+ }
+ }
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: smart_delfiles
+ ****************************************************************************/
+
+static int smart_delfiles(void)
+{
+ FAR struct smart_filedesc_s *file;
+ int ndel;
+ int ret;
+ int i;
+ int j;
+
+ /* Are there any files to be deleted? */
+
+ int nfiles = g_nfiles - g_ndeleted;
+ if (nfiles < 1)
+ {
+ return 0;
+ }
+
+ /* Yes... How many files should we delete? */
+
+ ndel = (rand() % nfiles) + 1;
+
+ /* Now pick which files to delete */
+
+ for (i = 0; i < ndel; i++)
+ {
+ /* Guess a file index */
+
+ int ndx = (rand() % (g_nfiles - g_ndeleted));
+
+ /* And delete the next undeleted file after that random index */
+
+ for (j = ndx + 1; j != ndx;)
+ {
+ file = &g_files[j];
+ if (file->name && !file->deleted)
+ {
+ ret = unlink(file->name);
+ if (ret < 0)
+ {
+ message("ERROR: Unlink %d failed: %d\n", i+1, errno);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" File index: %d\n", j);
+ }
+ else
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message(" Deleted file %s\n", file->name);
+#endif
+ file->deleted = true;
+ g_ndeleted++;
+ break;
+ }
+ }
+
+ /* Increment the index and test for wrap-around */
+
+ if (++j >= CONFIG_EXAMPLES_SMART_MAXOPEN)
+ {
+ j = 0;
+ }
+
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: smart_delallfiles
+ ****************************************************************************/
+
+static int smart_delallfiles(void)
+{
+ FAR struct smart_filedesc_s *file;
+ int ret;
+ int i;
+
+ for (i = 0; i < CONFIG_EXAMPLES_SMART_MAXOPEN; i++)
+ {
+ file = &g_files[i];
+ if (file->name)
+ {
+ ret = unlink(file->name);
+ if (ret < 0)
+ {
+ message("ERROR: Unlink %d failed: %d\n", i+1, errno);
+ message(" File name: %s\n", file->name);
+ message(" File size: %d\n", file->len);
+ message(" File index: %d\n", i);
+ }
+ else
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message(" Deleted file %s\n", file->name);
+#endif
+ smart_freefile(file);
+ }
+ }
+ }
+
+ g_nfiles = 0;
+ g_ndeleted = 0;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: smart_directory
+ ****************************************************************************/
+
+static int smart_directory(void)
+{
+ DIR *dirp;
+ FAR struct dirent *entryp;
+ int number;
+
+ /* Open the directory */
+
+ dirp = opendir(CONFIG_EXAMPLES_SMART_MOUNTPT);
+
+ if (!dirp)
+ {
+ /* Failed to open the directory */
+
+ message("ERROR: Failed to open directory '%s': %d\n",
+ CONFIG_EXAMPLES_SMART_MOUNTPT, errno);
+ return ERROR;
+ }
+
+ /* Read each directory entry */
+
+ message("Directory:\n");
+ number = 1;
+ do
+ {
+ entryp = readdir(dirp);
+ if (entryp)
+ {
+ message("%2d. Type[%d]: %s Name: %s\n",
+ number, entryp->d_type,
+ entryp->d_type == DTYPE_FILE ? "File " : "Error",
+ entryp->d_name);
+ }
+
+ number++;
+ }
+ while (entryp != NULL);
+
+ closedir(dirp);
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: smart_main
+ ****************************************************************************/
+
+int smart_main(int argc, char *argv[])
+{
+ FAR struct mtd_dev_s *mtd;
+ unsigned int i;
+ int ret;
+
+ /* Seed the random number generated */
+
+ srand(0x93846);
+
+ /* Create and initialize a RAM MTD device instance */
+
+#ifdef CONFIG_EXAMPLES_SMART_ARCHINIT
+ mtd = smart_archinitialize();
+#else
+ mtd = rammtd_initialize(g_simflash, EXAMPLES_SMART_BUFSIZE);
+#endif
+ if (!mtd)
+ {
+ message("ERROR: Failed to create RAM MTD instance\n");
+ msgflush();
+ exit(1);
+ }
+
+ /* Initialize to provide SMART on an MTD interface */
+
+ MTD_IOCTL(mtd, MTDIOC_BULKERASE, 0);
+ ret = smart_initialize(1, mtd);
+ if (ret < 0)
+ {
+ message("ERROR: SMART initialization failed: %d\n", -ret);
+ msgflush();
+ exit(2);
+ }
+
+ /* Creaet a SMARTFS filesystem */
+
+ ret = mksmartfs("/dev/smart1");
+
+ /* Mount the file system */
+
+ ret = mount("/dev/smart1", CONFIG_EXAMPLES_SMART_MOUNTPT, "smartfs", 0, NULL);
+ if (ret < 0)
+ {
+ message("ERROR: Failed to mount the SMART volume: %d\n", errno);
+ msgflush();
+ exit(3);
+ }
+
+ /* Set up memory monitoring */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmbefore = mallinfo();
+ g_mmprevious = g_mmbefore;
+#else
+ (void)mallinfo(&g_mmbefore);
+ memcpy(&g_mmprevious, &g_mmbefore, sizeof(struct mallinfo));
+#endif
+
+ /* Loop a few times ... file the file system with some random, files,
+ * delete some files randomly, fill the file system with more random file,
+ * delete, etc. This beats the FLASH very hard!
+ */
+
+#if CONFIG_EXAMPLES_SMART_NLOOPS == 0
+ for (i = 0; ; i++)
+#else
+ for (i = 1; i <= CONFIG_EXAMPLES_SMART_NLOOPS; i++)
+#endif
+ {
+ /* Write a files to the SMART file system until either (1) all of the
+ * open file structures are utilized or until (2) SMART reports an error
+ * (hopefully that the file system is full)
+ */
+
+ message("\n=== FILLING %d =============================\n", i);
+ ret = smart_fillfs();
+ message("Filled file system\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+
+ /* Directory listing */
+
+ smart_directory();
+
+ /* Verify all files written to FLASH */
+
+ ret = smart_verifyfs();
+ if (ret < 0)
+ {
+ message("ERROR: Failed to verify files\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+ }
+ else
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message("Verified!\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+#endif
+ }
+
+ /* Delete some files */
+
+ message("\n=== DELETING %d ============================\n", i);
+ ret = smart_delfiles();
+ if (ret < 0)
+ {
+ message("ERROR: Failed to delete files\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+ }
+ else
+ {
+ message("Deleted some files\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+ }
+
+ /* Directory listing */
+
+ smart_directory();
+
+ /* Verify all files written to FLASH */
+
+ ret = smart_verifyfs();
+ if (ret < 0)
+ {
+ message("ERROR: Failed to verify files\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+ }
+ else
+ {
+#if CONFIG_EXAMPLES_SMART_VERBOSE != 0
+ message("Verified!\n");
+ message(" Number of files: %d\n", g_nfiles);
+ message(" Number deleted: %d\n", g_ndeleted);
+#endif
+ }
+
+ /* Show memory usage */
+
+ smart_loopmemusage();
+ msgflush();
+ }
+
+ /* Delete all files then show memory usage again */
+
+ smart_delallfiles();
+ smart_endmemusage();
+ msgflush();
+ return 0;
+}
+
diff --git a/apps/examples/smart_test/smart_test.c b/apps/examples/smart_test/smart_test.c
index 3f8e42449..efce1b0bf 100644
--- a/apps/examples/smart_test/smart_test.c
+++ b/apps/examples/smart_test/smart_test.c
@@ -53,7 +53,7 @@
****************************************************************************/
#define SMART_TEST_LINE_COUNT 2000
-#define SMART_TEST_SEEK_WRITE_COUNT 12000
+#define SMART_TEST_SEEK_WRITE_COUNT 2000
/****************************************************************************
* Private data
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 8b8c3152d..1d10872fc 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -4651,7 +4651,7 @@
* configs/sim/mtdpart: A new configuration to test MTD
partitions (2013-4-30).
* configs/sim/mkroe-stm32f4: Support for the MikroElektronika
- Mikromedia for STM32F4 development board (from Ken Petit, 2013-4-30).
+ Mikromedia for STM32F4 development board (from Ken Pettit, 2013-4-30).
* fs/smartfs: Add Ken Pettits SMART FS (2013-4-30).
* include/nuttx/mtd.h and most MTD drivers: Add support for
(optional) method to perform byte oriented writes if so configured
@@ -4663,3 +4663,9 @@
(option) byte write method (2013-5-3).
* arch/arm/src/kl: Repartitioning of definitions in headef files
from Alan Carvalho de Assis (2013-5-3).
+ * drivers/mtd/smart.c, fs/smart, and other files: SMART file system
+ now makes use of the MTD byte write capabilities when present (from
+ Ken Pettit, 2013-5-3).
+ * drivers/mtd/m25px.c: Some rearchitecting to use the byte write
+ capability (when possible) and to use 4KB sectors for the erase block
+ size when the part supports it (Ken Pettit, 2013-5-3).
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index f758564ea..322667449 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -2552,6 +2552,19 @@ nsh>
<p>
<b>STMicro STM32F4-Discovery (STM32 F4 family)</b>.
This port uses the STMicro STM32F4-Discovery board featuring the STM32F407VGT6 MCU.
+ The STM32F407VGT6 is a 168MHz Cortex-M4 operation with 1Mbit Flash memory and 128kbytes.
+ The board features:
+ </p>
+ <ul>
+ <li>On-board ST-LINK/V2 for programming and debugging,</li>
+ <li>LIS302DL, ST MEMS motion sensor, 3-axis digital output accelerometer,</li>
+ <li>MP45DT02, ST MEMS audio sensor, omni-directional digital microphone,</li>
+ <li>CS43L22, audio DAC with integrated class D speaker driver,</li>
+ <li>Eight LEDs and two push-buttons,</li>
+ <li>USB OTG FS with micro-AB connector, and</li>
+ <li>Easy access to most MCU pins.</li>
+ </ul>
+ <p>
Refer to the <a href="http://www.st.com/internet/evalboard/product/252419.jsp">STMicro web site</a> for further information about this board.
</p>
<ul>
@@ -2571,6 +2584,38 @@ nsh>
<td><br></td>
<td>
<p>
+ <b>MikroElektronika Mikromedia for STM32F4</b>.
+ This is another board supported by NuttX that uses the same STM32F407VGT6 MCU as does the STM32F4-Discovery board.
+ This board, however, has very different on-board peripherals than does the STM32F4-Discovery:
+ </p>
+ <ul>
+ <li>TFT display with touch panel,</li>
+ <li>VS1053 stereo audio codec with headphone jack,</li>
+ <li>SD card slot,</li>
+ <li>Serial FLASH memory,</li>
+ <li>USB OTG FS with micro-AB connector, and</li>
+ <li>Battery connect and batter charger circuit.</li>
+ </ul>
+ <p>
+ See the <a href="http://www.mikroe.com/mikromedia/stm32-m4/">Mikroelektronika website<a> for more information about this board.
+ </p>
+ <ul>
+ <p>
+ <b>STATUS:</b>
+ The basic port for the Mikromedia STM32 M4 was contributed by Ken Petit and was first released in NuttX-6.128.
+ All drivers for the STM32 F4 family may be used with this board as well.
+ </p>
+ </ul>
+ </td>
+</tr>
+<tr>
+ <td><br></td>
+ <td><hr></td>
+</tr>
+<tr>
+ <td><br></td>
+ <td>
+ <p>
<b>STMicro STM32 F427/437</b>.
General architectural support was provided for the F427/437 family in NuttX 4.27.
Specific support includes the STM32F427I, STM32F427Z, and STM32F427V chips.
diff --git a/nuttx/configs/mikroe-stm32f4/Kconfig b/nuttx/configs/mikroe-stm32f4/Kconfig
index 8e55f0d17..0790f123a 100644
--- a/nuttx/configs/mikroe-stm32f4/Kconfig
+++ b/nuttx/configs/mikroe-stm32f4/Kconfig
@@ -5,53 +5,94 @@
if ARCH_BOARD_MIKROE_STM32F4
-config PM_BUTTONS
- bool "PM Button support"
+config MIKROE_FLASH
+ bool "MTD driver for onboard 1M FLASH"
default n
- depends on PM && ARCH_IRQBUTTONS
+ select MTD
+ select MTD_M25P
+ select MTD_SMART
+ select FS_SMARTFS
+ select STM32_SPI3
+ select MTD_BYTE_WRITE
---help---
- Enable PM button EXTI interrupts to support PM testing
+ Configures an MTD device for use with the onboard flash
-config PM_BUTTON_ACTIVITY
- int "Button PM activity weight"
- default 10
- depends on PM_BUTTONS
+config MIKROE_FLASH_MINOR
+ int "Minor number for the FLASH /dev/smart entry"
+ default 0
+ depends on MIKROE_FLASH
+ ---help---
+ Sets the minor number for the FLASH MTD /dev entry
+
+config MIKROE_FLASH_PART
+ bool "Enable partition support on FLASH"
+ default n
+ depends on MIKROE_FLASH
+ ---help---
+ Enables creation of partitions on the FLASH
+
+config MIKROE_FLASH_PART_LIST
+ string "Flash partition size list"
+ default "256,768"
+ depends on MIKROE_FLASH_PART
+ ---help---
+ Comma separated list of partition sizes in KB
+
+config MIKROE_RAMMTD
+ bool "MTD driver for SMARTFS RAM disk"
+ default n
+ select MTD
+ select RAMMTD
---help---
- The activity weight to report to the power management subsystem when a button is pressed.
+ Configures an MTD based RAM device for use with SMARTFS.
+
+config MIKROE_RAMMTD_MINOR
+ int "Minor number for RAM /dev/smart entry"
+ default 1
+ depends on MIKROE_RAMMTD
+ ---help---
+ Sets the minor number for the RAM MTD /dev entry
+
+config MIKROE_RAMMTD_SIZE
+ int "Size in KB of the RAM device to create"
+ default 32
+ depends on MIKROE_RAMMTD
+ ---help---
+ Sets the size of static RAM allocation for the SMART RAM device
config PM_ALARM_SEC
int "PM_STANDBY delay (seconds)"
default 15
depends on PM && RTC_ALARM
- --help---
+ ---help---
Number of seconds to wait in PM_STANDBY before going to PM_STANDBY mode.
config PM_ALARM_NSEC
int "PM_STANDBY delay (nanoseconds)"
default 0
depends on PM && RTC_ALARM
- --help---
+ ---help---
Number of additional nanoseconds to wait in PM_STANDBY before going to PM_STANDBY mode.
config PM_SLEEP_WAKEUP
bool "PM_SLEEP wake-up alarm"
default n
depends on PM && RTC_ALARM
- --help---
+ ---help---
Wake-up of PM_SLEEP mode after a delay and resume normal operation.
config PM_SLEEP_WAKEUP_SEC
int "PM_SLEEP delay (seconds)"
default 10
depends on PM && RTC_ALARM
- --help---
+ ---help---
Number of seconds to wait in PM_SLEEP before going to PM_STANDBY mode.
config PM_SLEEP_WAKEUP_NSEC
int "PM_SLEEP delay (nanoseconds)"
default 0
depends on PM && RTC_ALARM
- --help---
+ ---help---
Number of additional nanoseconds to wait in PM_SLEEP before going to PM_STANDBY mode.
endif
diff --git a/nuttx/configs/mikroe-stm32f4/README.txt b/nuttx/configs/mikroe-stm32f4/README.txt
index ed4ecbf2c..7d46fbc5c 100644
--- a/nuttx/configs/mikroe-stm32f4/README.txt
+++ b/nuttx/configs/mikroe-stm32f4/README.txt
@@ -2,7 +2,20 @@ README
======
This README discusses issues unique to NuttX configurations for the
-MikroElektronika Mikromedia for STM32F4 development board.
+MikroElektronika Mikromedia for STM32F4 development board. This is
+another board support by NuttX that uses the same STM32F407VGT6 MCU
+as does the STM32F4-Discovery board. This board, however, has very
+different on-board peripherals than does the STM32F4-Discovery:
+
+ - TFT display with touch panel,
+ - VS1053 stereo audio codec with headphone jack,
+ - SD card slot,
+ - Serial FLASH memory,
+ - USB OTG FS with micro-AB connector, and
+ - Battery connect and batter charger circuit.
+
+See the http://www.mikroe.com/mikromedia/stm32-m4/ for more information
+about this board.
Contents
========
diff --git a/nuttx/configs/mikroe-stm32f4/src/up_nsh.c b/nuttx/configs/mikroe-stm32f4/src/up_nsh.c
index e92a02e83..226a715f6 100644
--- a/nuttx/configs/mikroe-stm32f4/src/up_nsh.c
+++ b/nuttx/configs/mikroe-stm32f4/src/up_nsh.c
@@ -128,9 +128,14 @@
# define CONFIG_EXAMPLES_SMART_NEBLOCKS (22)
# endif
-# undef CONFIG_EXAMPLES_SMART_BUFSIZE
-# define CONFIG_EXAMPLES_SMART_BUFSIZE \
- (CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_SMART_NEBLOCKS)
+#ifdef CONFIG_MIKROE_RAMMTD
+# ifndef CONFIG_MIKROE_RAMMTD_MINOR
+# define CONFIG_MIKROE_RAMMTD_MINOR 1
+# endif
+# ifndef CONFIG_MIKROE_RAMMTD_SIZE
+# define CONFIG_MIKROE_RAMMTD_SIZE 32
+# endif
+#endif
/* Debug ********************************************************************/
@@ -151,11 +156,6 @@
/****************************************************************************
* Private Data
****************************************************************************/
-/* Pre-allocated simulated flash */
-
-#ifdef CONFIG_RAMMTD
-//static uint8_t g_simflash[CONFIG_EXAMPLES_SMART_BUFSIZE];
-#endif
/****************************************************************************
* Public Functions
@@ -197,7 +197,7 @@ int nsh_archinitialize(void)
/* Now bind the SPI interface to the M25P8 SPI FLASH driver */
-#ifdef CONFIG_MTD
+#if defined(CONFIG_MTD) && defined(CONFIG_MIKROE_FLASH)
message("nsh_archinitialize: Bind SPI to the SPI flash driver\n");
mtd = m25p_initialize(spi);
if (!mtd)
@@ -208,28 +208,78 @@ int nsh_archinitialize(void)
{
message("nsh_archinitialize: Successfully bound SPI port 3 to the SPI FLASH driver\n");
- /* Now initialize a SMART Flash block device and bind it to the MTD device */
+#ifdef CONFIG_MIKROE_FLASH_PART
+ {
+ int partno;
+ int partsize;
+ int partoffset;
+ const char *partstring = CONFIG_MIKROE_FLASH_PART_LIST;
+ const char *ptr;
+ FAR struct mtd_dev_s *mtd_part;
+ char partname[4];
+
+ /* Now create a partition on the FLASH device */
+
+ partno = 0;
+ ptr = partstring;
+ partoffset = 0;
+ while (*ptr != '\0')
+ {
+ /* Get the partition size */
+
+ partsize = atoi(ptr);
+ mtd_part = mtd_partition(mtd, partoffset, (partsize>>2)*16);
+ partoffset += (partsize >> 2) * 16;
+
+ /* Now initialize a SMART Flash block device and bind it to the MTD device */
#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
- smart_initialize(0, mtd);
+ sprintf(partname, "p%d", partno);
+ smart_initialize(CONFIG_MIKROE_FLASH_MINOR, mtd_part, partname);
#endif
+
+ /* Update the pointer to point to the next size in the list */
+
+ while ((*ptr >= '0') && (*ptr <= '9'))
+ {
+ ptr++;
+ }
+
+ if (*ptr == ',')
+ {
+ ptr++;
+ }
+
+ /* Increment the part number */
+
+ partno++;
+ }
+ }
+#else /* CONFIG_MIKROE_FLASH_PART */
+
+ /* Configure the device with no partition support */
+
+ smart_initialize(CONFIG_MIKROE_FLASH_MINOR, mtd, NULL);
+
+#endif /* CONFIG_MIKROE_FLASH_PART */
}
/* Create a RAM MTD device if configured */
-#ifdef CONFIG_RAMMTD
+#if defined(CONFIG_RAMMTD) && defined(CONFIG_MIKROE_RAMMTD)
{
- uint8_t *start = (uint8_t *) kmalloc(CONFIG_EXAMPLES_SMART_BUFSIZE);
- mtd = rammtd_initialize(start, CONFIG_EXAMPLES_SMART_BUFSIZE);
+ uint8_t *start = (uint8_t *) kmalloc(CONFIG_MIKROE_RAMMTD_SIZE * 1024);
+ mtd = rammtd_initialize(start, CONFIG_MIKROE_RAMMTD_SIZE * 1024);
mtd->ioctl(mtd, MTDIOC_BULKERASE, 0);
/* Now initialize a SMART Flash block device and bind it to the MTD device */
+
#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
- smart_initialize(1, mtd);
+ smart_initialize(CONFIG_MIKROE_RAMMTD_MINOR, mtd, NULL);
#endif
}
-#endif /* CONFIG_RAMMTD */
+#endif /* CONFIG_RAMMTD && CONFIG_MIKROE_RAMMTD */
#endif /* CONFIG_MTD */
#endif /* CONFIG_STM32_SPI3 */
diff --git a/nuttx/configs/mikroe-stm32f4/usbnsh/defconfig b/nuttx/configs/mikroe-stm32f4/usbnsh/defconfig
index 29e948be5..3340a95e6 100644
--- a/nuttx/configs/mikroe-stm32f4/usbnsh/defconfig
+++ b/nuttx/configs/mikroe-stm32f4/usbnsh/defconfig
@@ -16,7 +16,7 @@ CONFIG_HOST_LINUX=y
#
# Build Configuration
#
-# CONFIG_APPS_DIR="../apps"
+CONFIG_APPS_DIR="../apps"
# CONFIG_BUILD_2PASS is not set
#
@@ -38,27 +38,8 @@ CONFIG_RAW_BINARY=y
#
# Debug Options
#
-CONFIG_DEBUG=y
-# CONFIG_DEBUG_VERBOSE is not set
-
-#
-# Subsystem Debug Options
-#
-# CONFIG_DEBUG_MM is not set
-# CONFIG_DEBUG_SCHED is not set
-# CONFIG_DEBUG_USB is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_DEBUG_LIB is not set
-# CONFIG_DEBUG_BINFMT is not set
-# CONFIG_DEBUG_GRAPHICS is not set
-
-#
-# Driver Debug Options
-#
-# CONFIG_DEBUG_ANALOG is not set
-# CONFIG_DEBUG_SPI is not set
-# CONFIG_DEBUG_GPIO is not set
-CONFIG_DEBUG_SYMBOLS=y
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_SYMBOLS is not set
#
# System Type
@@ -104,7 +85,6 @@ CONFIG_ARCH_HAVE_CMNVECTOR=y
# CONFIG_ARCH_FPU is not set
CONFIG_ARCH_HAVE_MPU=y
# CONFIG_ARMV7M_MPU is not set
-# CONFIG_DEBUG_HARDFAULT is not set
#
# ARMV7M Configuration Options
@@ -310,6 +290,13 @@ CONFIG_NSH_MMCSDSPIPORTNO=0
#
# Board-Specific Options
#
+CONFIG_MIKROE_FLASH=y
+CONFIG_MIKROE_FLASH_MINOR=0
+CONFIG_MIKROE_FLASH_PART=y
+CONFIG_MIKROE_FLASH_PART_LIST="256,768"
+CONFIG_MIKROE_RAMMTD=y
+CONFIG_MIKROE_RAMMTD_MINOR=1
+CONFIG_MIKROE_RAMMTD_SIZE=32
#
# RTOS Features
@@ -408,21 +395,27 @@ CONFIG_MMCSD_SPI=y
CONFIG_MMCSD_SPICLOCK=20000000
# CONFIG_MMCSD_SDIO is not set
CONFIG_MTD=y
-# CONFIG_MTD_PARTITION is not set
+
+#
+# MTD Configuration
+#
+CONFIG_MTD_PARTITION=y
+CONFIG_MTD_BYTE_WRITE=y
+
+#
+# MTD Device Drivers
+#
CONFIG_RAMMTD=y
CONFIG_RAMMTD_BLOCKSIZE=512
CONFIG_RAMMTD_ERASESIZE=4096
CONFIG_RAMMTD_ERASESTATE=0xff
# CONFIG_RAMMTD_FLASHSIM is not set
-CONFIG_RAMMTD_SMART=y
# CONFIG_MTD_AT24XX is not set
# CONFIG_MTD_AT45DB is not set
CONFIG_MTD_M25P=y
CONFIG_M25P_SPIMODE=0
CONFIG_M25P_MANUFACTURER=0x1C
CONFIG_M25P_MEMORY_TYPE=0x31
-CONFIG_M25P_SUBSECTOR_ERASE=y
-CONFIG_M25P_BYTEWRITE=y
CONFIG_MTD_SMART=y
CONFIG_MTD_SMART_SECTOR_SIZE=512
# CONFIG_MTD_RAMTRON is not set
@@ -441,7 +434,6 @@ CONFIG_SERIAL_REMOVABLE=y
CONFIG_ARCH_HAVE_USART2=y
CONFIG_MCU_SERIAL=y
CONFIG_STANDARD_SERIAL=y
-# CONFIG_SERIAL_TIOCSERGSTRUCT is not set
# CONFIG_USART2_SERIAL_CONSOLE is not set
CONFIG_NO_SERIAL_CONSOLE=y
@@ -529,7 +521,7 @@ CONFIG_FS_ROMFS=y
CONFIG_FS_SMARTFS=y
CONFIG_SMARTFS_ERASEDSTATE=0xff
CONFIG_SMARTFS_MAXNAMLEN=16
-CONFIG_SMARTFS_MULTI_ROOT_DIRS=y
+# CONFIG_SMARTFS_MULTI_ROOT_DIRS is not set
# CONFIG_FS_BINFS is not set
#
@@ -650,6 +642,7 @@ CONFIG_EXAMPLES_NSH=y
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXCONSOLE is not set
# CONFIG_EXAMPLES_NXFFS is not set
+# CONFIG_EXAMPLES_SMART is not set
# CONFIG_EXAMPLES_NXFLAT is not set
# CONFIG_EXAMPLES_NXHELLO is not set
# CONFIG_EXAMPLES_NXIMAGE is not set
@@ -664,8 +657,8 @@ CONFIG_EXAMPLES_NSH=y
# CONFIG_EXAMPLES_ROMFS is not set
# CONFIG_EXAMPLES_SENDMAIL is not set
# CONFIG_EXAMPLES_SERLOOP is not set
-CONFIG_EXAMPLES_FLASH_TEST=y
-CONFIG_EXAMPLES_SMART_TEST=y
+# CONFIG_EXAMPLES_FLASH_TEST is not set
+# CONFIG_EXAMPLES_SMART_TEST is not set
# CONFIG_EXAMPLES_TELNETD is not set
# CONFIG_EXAMPLES_THTTPD is not set
# CONFIG_EXAMPLES_TIFF is not set
@@ -774,23 +767,13 @@ CONFIG_NSH_LINELEN=64
CONFIG_NSH_NESTDEPTH=3
# CONFIG_NSH_DISABLESCRIPT is not set
# CONFIG_NSH_DISABLEBG is not set
-CONFIG_NSH_ROMFSETC=y
-# CONFIG_NSH_ROMFSRC is not set
-CONFIG_NSH_ROMFSMOUNTPT="/etc"
-CONFIG_NSH_INITSCRIPT="init.d/rcS"
-CONFIG_NSH_ROMFSDEVNO=0
-CONFIG_NSH_ROMFSSECTSIZE=64
-CONFIG_NSH_FATDEVNO=0
-CONFIG_NSH_FATSECTSIZE=512
-CONFIG_NSH_FATNSECTORS=1024
-CONFIG_NSH_FATMOUNTPT="/tmp"
+# CONFIG_NSH_ROMFSETC is not set
CONFIG_NSH_CONSOLE=y
# CONFIG_NSH_USBCONSOLE is not set
#
# USB Trace Support
#
-# CONFIG_NSH_USBDEV_TRACE is not set
# CONFIG_NSH_CONDEV is not set
CONFIG_NSH_ARCHINIT=y
diff --git a/nuttx/configs/stm32f4discovery/README.txt b/nuttx/configs/stm32f4discovery/README.txt
index f5a261410..684c916f5 100644
--- a/nuttx/configs/stm32f4discovery/README.txt
+++ b/nuttx/configs/stm32f4discovery/README.txt
@@ -2,7 +2,20 @@ README
======
This README discusses issues unique to NuttX configurations for the
-STMicro STM32F4Discovery development board.
+STMicro STM32F4Discovery development board featuring the STM32F407VGT6
+MCU. The STM32F407VGT6 is a 168MHz Cortex-M4 operation with 1Mbit Flash
+memory and 128kbytes. The board features:
+
+ - On-board ST-LINK/V2 for programming and debugging,
+ - LIS302DL, ST MEMS motion sensor, 3-axis digital output accelerometer,
+ - MP45DT02, ST MEMS audio sensor, omni-directional digital microphone,
+ - CS43L22, audio DAC with integrated class D speaker driver,
+ - Eight LEDs and two push-buttons,
+ - USB OTG FS with micro-AB connector, and
+ - Easy access to most MCU pins.
+
+Refer to http://www.st.com/internet/evalboard/product/252419.jsp for
+further information about this board.
Contents
========
diff --git a/nuttx/drivers/mtd/Kconfig b/nuttx/drivers/mtd/Kconfig
index 310f494d8..4754fbeb7 100644
--- a/nuttx/drivers/mtd/Kconfig
+++ b/nuttx/drivers/mtd/Kconfig
@@ -64,13 +64,6 @@ config RAMMTD_FLASHSIM
RAMMTD_FLASHSIM will add some extra logic to improve the level of
FLASH simulation.
-config RAMMTD_SMART
- bool "SMART block driver support in the RAM MTD driver"
- default n
- ---help---
- Builds in additional ioctl and interface code to support the
- SMART block driver / filesystem.
-
endif
config MTD_AT24XX
@@ -139,30 +132,14 @@ config M25P_MEMORY_TYPE
---help---
The memory type for M25 "P" series is 0x20, but the driver also supports "F" series
devices, such as the EON EN25F80 part which adds a 4K sector erase capability. The
- ID for "F" series parts from EON is 0x31.
-
-config M25P_SUBSECTOR_ERASE
- bool "Sub-Sector Erase"
- default n
- ---help---
- Some devices (such as the EON EN25F80) support a smaller erase block
- size (4K vs 64K). This option enables support for sub-sector erase.
- The SMART file system can take advantage of this option if it is enabled.
-
-config M25P_BYTEWRITE
- bool "Enable ByteWrite ioctl support"
- default n
- ---help---
- The M25P series of devices allow writing to a page with less than a full-page
- size of data. In this case, only the written bytes are updated without affecting
- the other bytes in the page. The SMART FS requires this option for proper operation.
+ memory type for "F" series parts from EON is 0x31. The 4K sector erase size will
+ automatically be enabled when filessytems that can use it are enabled, such as SMART.
endif
config MTD_SMART
bool "Sector Mapped Allocation for Really Tiny (SMART) Flash support"
default y
- select M25P_BYTEWRITE
---help---
The MP25x series of Flash devices are typically very small and have a very large
erase block size. This causes issues with the standard Flash Translation Layer
diff --git a/nuttx/drivers/mtd/m25px.c b/nuttx/drivers/mtd/m25px.c
index bfe21a7dd..17f7a0672 100644
--- a/nuttx/drivers/mtd/m25px.c
+++ b/nuttx/drivers/mtd/m25px.c
@@ -3,7 +3,7 @@
* Driver for SPI-based M25P1 (128Kbit), M25P64 (32Mbit), M25P64 (64Mbit), and
* M25P128 (128Mbit) FLASH (and compatible).
*
- * Copyright (C) 2009-2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009-2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -114,6 +114,7 @@
#define M25P_EN25F80_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
#define M25P_EN25F80_NPAGES 4096
#define M25P_EN25F80_SUBSECT_SHIFT 12 /* Sub-Sector size 1 << 12 = 4,096 */
+#define M25P_EN25F80_NSUBSECTORS 256
/* M25P32 capacity is 4,194,304 bytes:
* (64 sectors) * (65,536 bytes per sector)
@@ -203,7 +204,7 @@ struct m25p_dev_s
uint8_t pageshift; /* 8 */
uint16_t nsectors; /* 128 or 64 */
uint32_t npages; /* 32,768 or 65,536 */
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
+#ifdef CONFIG_MTD_SMART
uint8_t subsectorshift; /* 0, 12 or 13 (4K or 8K) */
#endif
};
@@ -219,13 +220,10 @@ static inline void m25p_unlock(FAR struct spi_dev_s *dev);
static inline int m25p_readid(struct m25p_dev_s *priv);
static void m25p_waitwritecomplete(struct m25p_dev_s *priv);
static void m25p_writeenable(struct m25p_dev_s *priv);
-static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t offset);
+static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t offset, uint8_t type);
static inline int m25p_bulkerase(struct m25p_dev_s *priv);
static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer,
off_t offset);
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
-static inline void m25p_subsectorerase(struct m25p_dev_s *priv, off_t offset);
-#endif
/* MTD driver methods */
@@ -236,6 +234,10 @@ static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, FAR const uint8_t *buf);
static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
FAR uint8_t *buffer);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t m25p_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
+ FAR const uint8_t *buffer);
+#endif
static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
/************************************************************************************
@@ -320,7 +322,7 @@ static inline int m25p_readid(struct m25p_dev_s *priv)
{
/* Okay.. is it a FLASH capacity that we understand? */
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
+#ifdef CONFIG_MTD_SMART
priv->subsectorshift = 0;
#endif
@@ -338,11 +340,11 @@ static inline int m25p_readid(struct m25p_dev_s *priv)
{
/* Save the FLASH geometry */
- priv->sectorshift = M25P_EN25F80_SECTOR_SHIFT;
- priv->nsectors = M25P_EN25F80_NSECTORS;
priv->pageshift = M25P_EN25F80_PAGE_SHIFT;
priv->npages = M25P_EN25F80_NPAGES;
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
+ priv->sectorshift = M25P_EN25F80_SECTOR_SHIFT;
+ priv->nsectors = M25P_EN25F80_NSECTORS;
+#ifdef CONFIG_MTD_SMART
priv->subsectorshift = M25P_EN25F80_SUBSECT_SHIFT;
#endif
return OK;
@@ -480,9 +482,20 @@ static void m25p_writeenable(struct m25p_dev_s *priv)
* Name: m25p_sectorerase
************************************************************************************/
-static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector)
+static void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector, uint8_t type)
{
- off_t offset = sector << priv->sectorshift;
+ off_t offset;
+
+#ifdef CONFIG_MTD_SMART
+ if (priv->subsectorshift > 0)
+ {
+ offset = sector << priv->subsectorshift;
+ }
+ else
+#endif
+ {
+ offset = sector << priv->sectorshift;
+ }
fvdbg("sector: %08lx\n", (long)sector);
@@ -502,55 +515,11 @@ static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector)
SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
- /* Send the "Sector Erase (SE)" instruction */
-
- (void)SPI_SEND(priv->dev, M25P_SE);
-
- /* Send the sector offset high byte first. For all of the supported
- * parts, the sector number is completely contained in the first byte
- * and the values used in the following two bytes don't really matter.
- */
-
- (void)SPI_SEND(priv->dev, (offset >> 16) & 0xff);
- (void)SPI_SEND(priv->dev, (offset >> 8) & 0xff);
- (void)SPI_SEND(priv->dev, offset & 0xff);
-
- /* Deselect the FLASH */
-
- SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
- fvdbg("Erased\n");
-}
-
-/************************************************************************************
- * Name: m25p_subsectorerase
- ************************************************************************************/
-
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
-static inline void m25p_subsectorerase(struct m25p_dev_s *priv, off_t subsector)
-{
- off_t offset = subsector << priv->subsectorshift;
-
- fvdbg("subsector: %9lx\n", (long)subsector);
-
- /* Wait for any preceding write to complete. We could simplify things by
- * perform this wait at the end of each write operation (rather than at
- * the beginning of ALL operations), but have the wait first will slightly
- * improve performance.
+ /* Send the "Sector Erase (SE)" or Sub-Sector Erase (SSE) instruction
+ * that was passed in as the erase type.
*/
- m25p_waitwritecomplete(priv);
-
- /* Send write enable instruction */
-
- m25p_writeenable(priv);
-
- /* Select this FLASH part */
-
- SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
-
- /* Send the "Sub-Sector Erase (SSE)" instruction */
-
- (void)SPI_SEND(priv->dev, M25P_SSE);
+ (void)SPI_SEND(priv->dev, type);
/* Send the sector offset high byte first. For all of the supported
* parts, the sector number is completely contained in the first byte
@@ -566,7 +535,6 @@ static inline void m25p_subsectorerase(struct m25p_dev_s *priv, off_t subsector)
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
fvdbg("Erased\n");
}
-#endif
/************************************************************************************
* Name: m25p_bulkerase
@@ -654,7 +622,7 @@ static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *bu
* Name: m25p_bytewrite
************************************************************************************/
-#ifdef CONFIG_M25P_BYTEWRITE
+#ifdef CONFIG_MTD_BYTE_WRITE
static inline void m25p_bytewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer,
off_t offset, uint16_t count)
{
@@ -711,13 +679,55 @@ static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblock
/* Lock access to the SPI bus until we complete the erase */
m25p_lock(priv->dev);
- while (blocksleft-- > 0)
+ while (blocksleft > 0)
{
- /* Erase each sector */
+#ifdef CONFIG_MTD_SMART
+ size_t sectorboundry;
+ size_t blkper;
+
+ /* If we have a smaller erase size, then we will find as many full
+ * sector erase blocks as possible to speed up the process instead of
+ * erasing everything in smaller chunks.
+ */
+
+ if (priv->subsectorshift > 0)
+ {
+ blkper = 1 << (priv->sectorshift - priv->subsectorshift);
+ sectorboundry = (startblock + blkper - 1) / blkper;
+ sectorboundry *= blkper;
- m25p_sectorerase(priv, startblock);
+ /* If we are on a sector boundry and have at least a full sector
+ * of blocks left to erase, then we can do a full sector erase.
+ */
+
+ if (startblock == sectorboundry && blocksleft >= blkper)
+ {
+ /* Do a full sector erase */
+
+ m25p_sectorerase(priv, startblock / blkper, M25P_SE);
+ startblock += blkper;
+ blocksleft -= blkper;
+ continue;
+ }
+ else
+ {
+ /* Just do a sub-sector erase */
+
+ m25p_sectorerase(priv, startblock, M25P_SSE);
+ startblock++;
+ blocksleft--;
+ continue;
+ }
+ }
+#endif
+
+ /* Not using sub-sector erase. Erase each full sector */
+
+ m25p_sectorerase(priv, startblock, M25P_SE);
startblock++;
+ blocksleft--;
}
+
m25p_unlock(priv->dev);
return (int)nblocks;
}
@@ -741,6 +751,7 @@ static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nb
{
return nbytes >> priv->pageshift;
}
+
return (int)nbytes;
}
@@ -766,8 +777,8 @@ static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t n
buffer += pagesize;
startblock++;
}
- m25p_unlock(priv->dev);
+ m25p_unlock(priv->dev);
return nblocks;
}
@@ -818,6 +829,78 @@ static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
}
/************************************************************************************
+ * Name: m25p_write
+ ************************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t m25p_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
+ FAR const uint8_t *buffer)
+{
+ FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
+ int startpage;
+ int endpage;
+ int count;
+ int index;
+ int pagesize;
+ int bytestowrite;
+
+ fvdbg("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes);
+
+ /* We must test if the offset + count crosses one or more pages
+ * and perform individual writes. The devices can only write in
+ * page increments.
+ */
+
+ startpage = offset / (1 << priv->pageshift);
+ endpage = (offset + nbytes) / (1 << priv->pageshift);
+
+ if (startpage == endpage)
+ {
+ /* All bytes within one programmable page. Just do the write. */
+
+ m25p_bytewrite(priv, buffer, offset, nbytes);
+ }
+ else
+ {
+ /* Write the 1st partial-page */
+
+ count = nbytes;
+ pagesize = (1 << priv->pageshift);
+ bytestowrite = pagesize - (offset & (pagesize-1));
+ m25p_bytewrite(priv, buffer, offset, bytestowrite);
+
+ /* Update offset and count */
+
+ offset += bytestowrite;
+ count -= bytestowrite;
+ index = bytestowrite;
+
+ /* Write full pages */
+
+ while (count >= pagesize)
+ {
+ m25p_bytewrite(priv, &buffer[index], offset, pagesize);
+
+ /* Update offset and count */
+
+ offset += pagesize;
+ count -= pagesize;
+ index += pagesize;
+ }
+
+ /* Now write any partial page at the end */
+
+ if (count > 0)
+ {
+ m25p_bytewrite(priv, &buffer[index], offset, count);
+ }
+ }
+
+ return nbytes;
+}
+#endif /* CONFIG_MTD_BYTE_WRITE */
+
+/************************************************************************************
* Name: m25p_ioctl
************************************************************************************/
@@ -844,15 +927,22 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
* appear so.
*/
- geo->blocksize = (1 << priv->pageshift);
- geo->erasesize = (1 << priv->sectorshift);
- geo->neraseblocks = priv->nsectors;
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
- geo->subsectorsize = (1 << priv->subsectorshift);
- geo->nsubsectors = priv->nsectors * (1 << (priv->sectorshift -
- priv->subsectorshift));
+ geo->blocksize = (1 << priv->pageshift);
+#ifdef CONFIG_MTD_SMART
+ if (priv->subsectorshift > 0)
+ {
+ geo->erasesize = (1 << priv->subsectorshift);
+ geo->neraseblocks = priv->nsectors * (1 << (priv->sectorshift -
+ priv->subsectorshift));
+ }
+ else
#endif
- ret = OK;
+ {
+ geo->erasesize = (1 << priv->sectorshift);
+ geo->neraseblocks = priv->nsectors;
+ }
+
+ ret = OK;
fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n",
geo->blocksize, geo->erasesize, geo->neraseblocks);
@@ -870,97 +960,6 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
}
break;
-#ifdef CONFIG_FS_SMARTFS
- case MTDIOC_GETCAPS:
- {
- ret = 0;
-#ifdef CONFIG_M25P_BYTEWRITE
- ret |= MTDIOC_CAPS_BYTEWRITE;
-#endif
-
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
- ret |= MTDIOC_CAPS_SECTERASE;
-#endif
- break;
- }
-#endif /* CONFIG_FS_SMARTFS */
-
-#ifdef CONFIG_M25P_SUBSECTOR_ERASE
- case MTDIOC_SECTERASE:
- {
- m25p_subsectorerase(priv, (off_t) arg);
- ret = OK;
- break;
- }
-#endif
-
-#ifdef CONFIG_M25P_BYTEWRITE
- case MTDIOC_BYTEWRITE:
- {
- struct mtd_byte_write_s *bytewrite = (struct mtd_byte_write_s *) arg;
- int startpage;
- int endpage;
- int count;
- int index;
- int pagesize;
- int bytestowrite;
- size_t offset;
-
- /* We must test if the offset + count crosses one or more pages
- * and perform individual writes. The devices can only write in
- * page increments.
- */
-
- startpage = bytewrite->offset / (1 << priv->pageshift);
- endpage = (bytewrite->offset + bytewrite->count) / (1 << priv->pageshift);
-
- if (startpage == endpage)
- {
- m25p_bytewrite(priv, bytewrite->buffer, bytewrite->offset,
- bytewrite->count);
- }
- else
- {
- /* Write the 1st partial-page */
-
- count = bytewrite->count;
- pagesize = (1 << priv->pageshift);
- offset = bytewrite->offset;
- bytestowrite = pagesize - (bytewrite->offset & (pagesize-1));
- m25p_bytewrite(priv, bytewrite->buffer, offset, bytestowrite);
-
- /* Update offset and count */
-
- offset += bytestowrite;
- count -= bytestowrite;
- index = bytestowrite;
-
- /* Write full pages */
-
- while (count >= pagesize)
- {
- m25p_bytewrite(priv, &bytewrite->buffer[index], offset, pagesize);
-
- /* Update offset and count */
-
- offset += pagesize;
- count -= pagesize;
- index += pagesize;
- }
-
- /* Now write any partial page at the end */
-
- if (count > 0)
- {
- m25p_bytewrite(priv, &bytewrite->buffer[index], offset, count);
- }
- }
-
- ret = OK;
- break;
- }
-#endif
-
case MTDIOC_XIPBASE:
default:
ret = -ENOTTY; /* Bad command */
@@ -1010,6 +1009,9 @@ FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
priv->mtd.bread = m25p_bread;
priv->mtd.bwrite = m25p_bwrite;
priv->mtd.read = m25p_read;
+#ifdef CONFIG_MTD_BYTE_WRITE
+ priv->mtd.write = m25p_write;
+#endif
priv->mtd.ioctl = m25p_ioctl;
priv->dev = dev;
diff --git a/nuttx/drivers/mtd/mtd_partition.c b/nuttx/drivers/mtd/mtd_partition.c
index 1bff0af9c..699a2fa5a 100644
--- a/nuttx/drivers/mtd/mtd_partition.c
+++ b/nuttx/drivers/mtd/mtd_partition.c
@@ -137,7 +137,7 @@ static bool part_bytecheck(FAR struct mtd_partition_s *priv, off_t byoff)
erasesize = priv->blocksize * priv->blkpererase;
readend = (byoff + erasesize - 1) / erasesize;
- return readend < priv->neraseblocks;
+ return readend <= priv->neraseblocks;
}
/****************************************************************************
@@ -410,6 +410,12 @@ static int part_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
* sector count (where the size of a sector is provided the by parent MTD
* driver).
*
+ * NOTE: Since there may be a number of MTD partition drivers operating on
+ * the same, underlying FLASH driver, that FLASH driver must be capable
+ * of enforcing mutually exclusive access to the FLASH device. Without
+ * partitions, that mutual exclusion would be provided by the file system
+ * above the FLASH driver.
+ *
****************************************************************************/
FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, off_t firstblock,
@@ -483,6 +489,9 @@ FAR struct mtd_dev_s *mtd_partition(FAR struct mtd_dev_s *mtd, off_t firstblock,
part->child.bwrite = part_bwrite;
part->child.read = mtd->read ? part_read : NULL;
part->child.ioctl = part_ioctl;
+#ifdef CONFIG_MTD_BYTE_WRITE
+ part->child.write = mtd->write ? part_write : NULL;
+#endif
part->parent = mtd;
part->firstblock = erasestart * blkpererase;
diff --git a/nuttx/drivers/mtd/rammtd.c b/nuttx/drivers/mtd/rammtd.c
index 461cd7d99..137f91f73 100644
--- a/nuttx/drivers/mtd/rammtd.c
+++ b/nuttx/drivers/mtd/rammtd.c
@@ -228,7 +228,7 @@ static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks
* Name: ram_readbytes
****************************************************************************/
-#ifdef CONFIG_RAMMTD_SMART
+#ifdef CONFIG_MTD_SMART
static ssize_t ram_read_bytes(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR uint8_t *buf)
{
@@ -329,6 +329,34 @@ static ssize_t ram_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
}
/****************************************************************************
+ * Name: ram_bytewrite
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t ram_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
+ size_t nbytes, FAR const uint8_t *buf)
+{
+ FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev;
+ off_t maxaddr;
+
+ DEBUGASSERT(dev && buf);
+
+ /* Don't let the write exceed the size of the ram buffer */
+
+ maxaddr = priv->nblocks * CONFIG_RAMMTD_ERASESIZE;
+ if (offset + nbytes > maxaddr)
+ {
+ return 0;
+ }
+
+ /* Then write the data to RAM */
+
+ ram_write(&priv->start[offset], buf, nbytes);
+ return nbytes;
+}
+#endif
+
+/****************************************************************************
* Name: ram_ioctl
****************************************************************************/
@@ -380,24 +408,6 @@ static int ram_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
}
break;
-#ifdef CONFIG_RAMMTD_SMART
- case MTDIOC_GETCAPS:
- {
- ret = MTDIOC_CAPS_BYTEWRITE;
- break;
- }
-
- case MTDIOC_BYTEWRITE:
- {
- struct mtd_byte_write_s *bytewrite = (struct mtd_byte_write_s *) arg;
-
- ram_write(&priv->start[bytewrite->offset], bytewrite->buffer,
- bytewrite->count);
- ret = OK;
- break;
- }
-#endif
-
default:
ret = -ENOTTY; /* Bad command */
break;
@@ -454,9 +464,14 @@ FAR struct mtd_dev_s *rammtd_initialize(FAR uint8_t *start, size_t size)
priv->mtd.bwrite = ram_bwrite;
priv->mtd.ioctl = ram_ioctl;
priv->mtd.erase = ram_erase;
+#ifdef CONFIG_MTD_BYTE_WRITE
+ priv->mtd.write = ram_bytewrite;
+#endif
-#ifdef CONFIG_RAMMTD_SMART
+#ifdef CONFIG_MTD_SMART
priv->mtd.read = ram_read_bytes;
+#else
+ priv->mtd.read = NULL;
#endif
priv->start = start;
diff --git a/nuttx/drivers/mtd/smart.c b/nuttx/drivers/mtd/smart.c
index 9de557b5f..35a367e5b 100644
--- a/nuttx/drivers/mtd/smart.c
+++ b/nuttx/drivers/mtd/smart.c
@@ -97,7 +97,7 @@
#define SMART_FMT_VERSION 1
-#define SMART_FIRST_ALLOC_SECTOR 16 /* First logical sector number we will
+#define SMART_FIRST_ALLOC_SECTOR 12 /* First logical sector number we will
* use for assignment of requested Alloc
* sectors. All enries below this are
* reserved (some for root dir entries,
@@ -134,6 +134,7 @@ struct smart_struct_s
FAR uint8_t *releasecount; /* Count of released sectors per erase block */
FAR uint8_t *freecount; /* Count of free sectors per erase block */
FAR char *rwbuffer; /* Our sector read/write buffer */
+ const FAR char *partname; /* Optional partition name */
uint8_t formatversion; /* Format version on the device */
uint8_t formatstatus; /* Indicates the status of the device format */
uint8_t namesize; /* Length of filenames on this device */
@@ -471,49 +472,21 @@ static int smart_setsectorsize(struct smart_struct_s *dev, uint16_t size)
{
uint32_t erasesize;
uint32_t totalsectors;
- int ret;
- /* Check if the device supports sub-sector erase regions. If it does, then
- * use the sub-sector erase size instead of the larger erase size to
- * provide finer granularity.
- */
+ /* Validate the size isn't zero so we don't divide by zero below */
-#ifdef CONFIG_MTD_SUBSECTOR_ERASE
- ret = MTD_IOCTL(dev->mtd, MTDIOC_GETCAPS, 0);
- if (ret >= 0)
+ if (size == 0)
{
- /* The block device supports the GETCAPS ioctl. Now check if sub-sector
- * erase is supported.
- */
-
- if (!(ret & MTDIOC_CAPS_SECTERASE))
- {
- /* Ensure the subsector size is zero */
- dev->geo.subsectorsize = 0;
- dev->geo.nsubsectors = 0;
- }
+ size = CONFIG_MTD_SMART_SECTOR_SIZE;
}
- /* Now calculate the variables */
-
- if (dev->geo.subsectorsize != 0)
- {
- /* Use the sub-sector erase size */
-
- erasesize = dev->geo.subsectorsize;
- dev->neraseblocks = dev->geo.nsubsectors;
- }
- else
-#endif /* CONFIG_MTD_SUBSECTOR_ERASE */
- {
- erasesize = dev->geo.erasesize;
- dev->neraseblocks = dev->geo.neraseblocks;
- }
+ erasesize = dev->geo.erasesize;
+ dev->neraseblocks = dev->geo.neraseblocks;
/* Most FLASH devices have erase size of 64K, but geo.erasesize is only
* 16 bits, so it will be zero
*/
-
+
if (erasesize == 0)
{
erasesize = 65536;
@@ -569,6 +542,74 @@ static int smart_setsectorsize(struct smart_struct_s *dev, uint16_t size)
}
/****************************************************************************
+ * Name: smart_bytewrite
+ *
+ * Description: Writes a non-page size count of bytes to the underlying
+ * MTD device. If the MTD driver supports a direct impl of
+ * write, then it uses it, otherwise it does a read-modify-write
+ * and depends on the architecture of the flash to only program
+ * bits that acutally changed.
+ *
+ ****************************************************************************/
+
+static ssize_t smart_bytewrite(struct smart_struct_s *dev, size_t offset,
+ int nbytes, const uint8_t *buffer)
+{
+ ssize_t ret;
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+ /* Check if the underlying MTD device supports write */
+
+ if (dev->mtd->write != NULL)
+ {
+ /* Use the MTD's write method to write individual bytes */
+
+ ret = dev->mtd->write(dev->mtd, offset, nbytes, buffer);
+ }
+ else
+#endif
+ {
+ /* Perform block-based read-modify-write */
+
+ uint16_t startblock;
+ uint16_t nblocks;
+
+ /* First calculate the start block and number of blocks affected */
+
+ startblock = offset / dev->geo.blocksize;
+ nblocks = (nbytes + dev->geo.blocksize-1) / dev->geo.blocksize;
+ DEBUGASSERT(nblocks <= dev->mtdBlksPerSector);
+
+ /* Do a block read */
+
+ ret = MTD_BREAD(dev->mtd, startblock, nblocks, (uint8_t *) dev->rwbuffer);
+ if (ret < 0)
+ {
+ fdbg("Error %d reading from device\n", -ret);
+ goto errout;
+ }
+
+ /* Modify the data */
+
+ memcpy(&dev->rwbuffer[offset - startblock * dev->geo.blocksize], buffer, nbytes);
+
+ /* Write the data back to the device */
+
+ ret = MTD_BWRITE(dev->mtd, startblock, nblocks, (uint8_t *) dev->rwbuffer);
+ if (ret < 0)
+ {
+ fdbg("Error %d writing to device\n", -ret);
+ goto errout;
+ }
+ }
+
+ ret = nbytes;
+
+errout:
+ return ret;
+}
+
+/****************************************************************************
* Name: smart_scan
*
* Description: Performs a scan of the MTD device searching for format
@@ -581,17 +622,17 @@ static int smart_scan(struct smart_struct_s *dev)
{
int sector;
int ret;
- int x;
+ int offset;
uint16_t totalsectors;
uint16_t sectorsize;
uint16_t logicalsector;
uint16_t seq1;
uint16_t seq2;
- char devname[18];
size_t readaddress;
struct smart_sect_header_s header;
- struct mtd_byte_write_s bytewrite;
#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
+ int x;
+ char devname[22];
struct smart_multiroot_device_s *rootdirdev;
#endif
@@ -675,7 +716,7 @@ static int smart_scan(struct smart_struct_s *dev)
}
#endif
- /* Test if this sector has been commited */
+ /* Test if this sector has been committed */
if ((header.status & SMART_STATUS_COMMITTED) ==
(CONFIG_SMARTFS_ERASEDSTATE & SMART_STATUS_COMMITTED))
@@ -763,7 +804,16 @@ static int smart_scan(struct smart_struct_s *dev)
for (x = 1; x < dev->rootdirentries; x++)
{
- snprintf(devname, 18, "/dev/smart%dd%d", dev->minor, x + 1);
+ if (dev->partname != NULL)
+ {
+ snprintf(dev->rwbuffer, sizeof(devname), "/dev/smart%d%s%d",
+ dev->minor, dev->partname, x+1);
+ }
+ else
+ {
+ snprintf(devname, sizeof(devname), "/dev/smart%dd%d", dev->minor,
+ x + 1);
+ }
/* Inode private data is a reference to a struct containing
* the SMART device structure and the root directory number.
@@ -792,9 +842,9 @@ static int smart_scan(struct smart_struct_s *dev)
/* Test for duplicate logical sectors on the device */
- if (dev->sMap[logicalsector] != -1)
+ if (dev->sMap[logicalsector] != 0xFFFF)
{
- /* TODO: Uh-oh, we found more than 1 physical sector claiming to be
+ /* Uh-oh, we found more than 1 physical sector claiming to be
* the * same logical sector. Use the sequence number information
* to resolve who wins.
*/
@@ -853,10 +903,13 @@ static int smart_scan(struct smart_struct_s *dev)
#else
header.status |= SMART_STATUS_RELEASED;
#endif
- bytewrite.offset = readaddress + offsetof(struct smart_sect_header_s, status);
- bytewrite.count = 1;
- bytewrite.buffer = &header.status;
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
+ offset = readaddress + offsetof(struct smart_sect_header_s, status);
+ ret = smart_bytewrite(dev, offset, 1, &header.status);
+ if (ret < 0)
+ {
+ fdbg("Error %d releasing duplicate sector\n", -ret);
+ goto err_out;
+ }
}
/* Update the logical to physical sector map */
@@ -886,9 +939,11 @@ err_out:
#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
static inline int smart_getformat(struct smart_struct_s *dev,
- struct smart_format_s *fmt, uint8_t rootdirnum)
+ struct smart_format_s *fmt,
+ uint8_t rootdirnum)
#else
-static inline int smart_getformat(struct smart_struct_s *dev, struct smart_format_s *fmt)
+static inline int smart_getformat(struct smart_struct_s *dev,
+ struct smart_format_s *fmt)
#endif
{
int ret;
@@ -914,8 +969,6 @@ static inline int smart_getformat(struct smart_struct_s *dev, struct smart_forma
}
}
- /* TODO: Determine if the underlying MTD device supports bytewrite */
-
/* Now fill in the structure */
if (dev->formatstatus == SMART_FMT_STAT_FORMATTED)
@@ -978,7 +1031,7 @@ static inline int smart_llformat(struct smart_struct_s *dev, unsigned long arg)
/* Erase the MTD device */
ret = MTD_IOCTL(dev->mtd, MTDIOC_BULKERASE, 0);
- if (ret != OK)
+ if (ret < 0)
{
return ret;
}
@@ -1180,8 +1233,9 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
bool collect = TRUE;
int x;
int ret;
+ size_t offset;
struct smart_sect_header_s *header;
- struct mtd_byte_write_s bytewrite;
+ uint8_t newstatus;
while (collect)
{
@@ -1196,8 +1250,6 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
{
releasedsectors += dev->releasecount[x];
if (dev->releasecount[x] > releasemax)
-// if (dev->releasecount[x] > releasemax &&
-// dev->freecount[x] < (dev->sectorsPerBlk >> 1))
{
releasemax = dev->releasecount[x];
collectblock = x;
@@ -1205,7 +1257,8 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
}
/* Test if the released sectors count is greater than the
- * free sectors. If it is, then we will do garbage collection */
+ * free sectors. If it is, then we will do garbage collection.
+ */
if (releasedsectors > dev->freesectors)
collect = TRUE;
@@ -1238,7 +1291,8 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
/* Perform collection on block with the most released sectors.
* First mark the block as having no free sectors so we don't
- * try to move sectors into the block we are trying to erase. */
+ * try to move sectors into the block we are trying to erase.
+ */
dev->freecount[collectblock] = 0;
@@ -1267,7 +1321,8 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
(CONFIG_SMARTFS_ERASEDSTATE & SMART_STATUS_RELEASED)))
{
/* This sector doesn't have live data (free or released).
- * just continue to the next sector and don't move it. */
+ * just continue to the next sector and don't move it.
+ */
continue;
}
@@ -1304,27 +1359,35 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
/* Commit the sector */
- bytewrite.offset = newsector * dev->mtdBlksPerSector * dev->geo.blocksize +
+ offset = newsector * dev->mtdBlksPerSector * dev->geo.blocksize +
offsetof(struct smart_sect_header_s, status);
#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
- header->status &= ~SMART_STATUS_COMMITTED;
+ newstatus = header->status & ~SMART_STATUS_COMMITTED;
#else
- header->status |= SMART_STATUS_COMMITTED;
+ newstatus = header->status | SMART_STATUS_COMMITTED;
#endif
- bytewrite.count = 1;
- bytewrite.buffer = &header->status;
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
+ ret = smart_bytewrite(dev, offset, 1, &newstatus);
+ if (ret < 0)
+ {
+ fdbg("Error %d committing new sector %d\n" -ret, newsector);
+ goto errout;
+ }
/* Release the old physical sector */
#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
- header->status &= ~SMART_STATUS_RELEASED;
+ newstatus = header->status & ~SMART_STATUS_RELEASED;
#else
- header->status |= SMART_STATUS_RELEASED;
+ newstatus = header->status | SMART_STATUS_RELEASED;
#endif
- bytewrite.offset = x * dev->mtdBlksPerSector * dev->geo.blocksize +
+ offset = x * dev->mtdBlksPerSector * dev->geo.blocksize +
offsetof(struct smart_sect_header_s, status);
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
+ ret = smart_bytewrite(dev, offset, 1, &newstatus);
+ if (ret < 0)
+ {
+ fdbg("Error %d releasing old sector %d\n" -ret, x);
+ goto errout;
+ }
/* Update the variables */
@@ -1334,17 +1397,7 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
/* Now erase the erase block */
-#ifdef CONFIG_MTD_SUBSECTOR_ERASE
- if (dev->geo.subsectorsize != 0)
- {
- /* Perform a sub-sector erase */
- MTD_IOCTL(dev->mtd, MTDIOC_SECTERASE, collectblock);
- }
- else
-#endif
- {
- MTD_ERASE(dev->mtd, collectblock, 1);
- }
+ MTD_ERASE(dev->mtd, collectblock, 1);
dev->freesectors += dev->releasecount[collectblock];
dev->freecount[collectblock] = dev->sectorsPerBlk;
@@ -1357,18 +1410,19 @@ static int smart_garbagecollect(struct smart_struct_s *dev)
/* Set the sector size in the 1st header */
uint8_t sectsize = dev->sectorsize >> 7;
- header = (struct smart_sect_header_s *) dev->rwbuffer;
#if ( CONFIG_SMARTFS_ERASEDSTATE == 0xFF )
- header->status = (uint8_t) ~SMART_STATUS_SIZEBITS | sectsize;
+ newstatus = (uint8_t) ~SMART_STATUS_SIZEBITS | sectsize;
#else
- header->status = (uint8_t) sectsize;
+ newstatus = (uint8_t) sectsize;
#endif
/* Write the sector size to the device */
- bytewrite.offset = offsetof(struct smart_sect_header_s, status);
- bytewrite.count = 1;
- bytewrite.buffer = &header->status;
- MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
+ offset = offsetof(struct smart_sect_header_s, status);
+ ret = smart_bytewrite(dev, offset, 1, &newstatus);
+ if (ret < 0)
+ {
+ fdbg("Error %d setting sector 0 size\n", -ret);
+ }
}
/* Update the block aging information in the format signature sector */
@@ -1402,15 +1456,15 @@ errout:
#ifdef CONFIG_FS_WRITABLE
static inline int smart_writesector(struct smart_struct_s *dev, unsigned long arg)
{
- int ret;
- uint16_t x;
- bool needsrelocate = FALSE;
- uint16_t mtdblock;
- uint16_t physsector;
- struct smart_read_write_s *req;
- struct smart_sect_header_s *header;
- struct mtd_byte_write_s bytewrite;
- uint8_t byte;
+ int ret;
+ uint16_t x;
+ bool needsrelocate = FALSE;
+ uint16_t mtdblock;
+ uint16_t physsector;
+ struct smart_read_write_s *req;
+ struct smart_sect_header_s *header;
+ size_t offset;
+ uint8_t byte;
fvdbg("Entry\n");
req = (struct smart_read_write_s *) arg;
@@ -1515,16 +1569,14 @@ static inline int smart_writesector(struct smart_struct_s *dev, unsigned long ar
/* Commit the new physical sector */
#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
- header->status &= ~SMART_STATUS_COMMITTED;
+ byte = header->status & ~SMART_STATUS_COMMITTED;
#else
- header->status |= SMART_STATUS_COMMITTED;
+ byte = header->status | SMART_STATUS_COMMITTED;
#endif
- bytewrite.offset = physsector * dev->mtdBlksPerSector *
- dev->geo.blocksize + offsetof(struct smart_sect_header_s, status);
- bytewrite.count = 1;
- bytewrite.buffer = (uint8_t *) &header->status;
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
- if (ret != OK)
+ offset = physsector * dev->mtdBlksPerSector * dev->geo.blocksize +
+ offsetof(struct smart_sect_header_s, status);
+ ret = smart_bytewrite(dev, offset, 1, &byte);
+ if (ret != 1)
{
fvdbg("Error committing physical sector %d\n", physsector);
ret = -EIO;
@@ -1534,13 +1586,13 @@ static inline int smart_writesector(struct smart_struct_s *dev, unsigned long ar
/* Release the old physical sector */
#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
- header->status &= ~SMART_STATUS_RELEASED;
+ byte = header->status & ~SMART_STATUS_RELEASED;
#else
- header->status |= SMART_STATUS_RELEASED;
+ byte = header->status | SMART_STATUS_RELEASED;
#endif
- bytewrite.offset = mtdblock * dev->geo.blocksize +
+ offset = mtdblock * dev->geo.blocksize +
offsetof(struct smart_sect_header_s, status);
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
+ ret = smart_bytewrite(dev, offset, 1, &byte);
/* Update releasecount for released sector and freecount for the
* newly allocated physical sector. */
@@ -1564,11 +1616,9 @@ static inline int smart_writesector(struct smart_struct_s *dev, unsigned long ar
/* Not relocated. Just write the portion of the sector that needs
* to be written. */
- bytewrite.offset = mtdblock * dev->geo.blocksize +
+ offset = mtdblock * dev->geo.blocksize +
sizeof(struct smart_sect_header_s) + req->offset;
- bytewrite.count = req->count;
- bytewrite.buffer = req->buffer;
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
+ ret = smart_bytewrite(dev, offset, req->count, req->buffer);
}
ret = OK;
@@ -1743,9 +1793,8 @@ static inline int smart_allocsector(struct smart_struct_s *dev, unsigned long re
* rescan and try again to "self heal" in case of a
* bug in our code? */
- fdbg("Couldn't find free sector when I expected too\n");
-
- /* Unlock the mutex if we add one */
+ fdbg("No free logical sector numbers! Free sectors = %d\n",
+ dev->freesectors);
return -EIO;
}
@@ -1827,7 +1876,7 @@ static inline int smart_freesector(struct smart_struct_s *dev, unsigned long
uint16_t physsector;
uint16_t block;
struct smart_sect_header_s header;
- struct mtd_byte_write_s bytewrite;
+ size_t offset;
/* Check if the logical sector is within bounds */
@@ -1875,11 +1924,9 @@ static inline int smart_freesector(struct smart_struct_s *dev, unsigned long
/* Write the status back to the device */
- bytewrite.offset = readaddr + offsetof(struct smart_sect_header_s, status);
- bytewrite.count = 1;
- bytewrite.buffer = &header.status;
- ret = MTD_IOCTL(dev->mtd, MTDIOC_BYTEWRITE, (unsigned long) &bytewrite);
- if (ret != OK)
+ offset = readaddr + offsetof(struct smart_sect_header_s, status);
+ ret = smart_bytewrite(dev, offset, 1, &header.status);
+ if (ret != 1)
{
fdbg("Error updating physicl sector %d status\n", physsector);
goto errout;
@@ -1900,15 +1947,7 @@ static inline int smart_freesector(struct smart_struct_s *dev, unsigned long
{
/* Erase the block */
-#ifdef CONFIG_MTD_SUBSECTOR_ERASE
- if (dev->geo.subsectorsize != 0)
- {
- /* Perform a sub-sector erase */
- MTD_IOCTL(dev->mtd, MTDIOC_SECTERASE, block);
- }
- else
-#endif
- MTD_ERASE(dev->mtd, block, 1);
+ MTD_ERASE(dev->mtd, block, 1);
dev->freesectors += dev->releasecount[block];
dev->releasecount[block] = 0;
@@ -2050,7 +2089,7 @@ ok_out:
*
****************************************************************************/
-int smart_initialize(int minor, FAR struct mtd_dev_s *mtd)
+int smart_initialize(int minor, FAR struct mtd_dev_s *mtd, const char *partname)
{
struct smart_struct_s *dev;
int ret = -ENOMEM;
@@ -2084,10 +2123,6 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd)
/* Set these to zero in case the device doesn't support them */
-#ifdef CONFIG_MTD_SUBSECTOR_ERASE
- dev->geo.subsectorsize= 0;
- dev->geo.nsubsectors = 0;
-#endif
ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->geo));
if (ret < 0)
{
@@ -2123,6 +2158,7 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd)
dev->formatstatus = SMART_FMT_STAT_UNKNOWN;
dev->namesize = CONFIG_SMARTFS_MAXNAMLEN;
+ dev->partname = partname;
#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
dev->minor = minor;
#endif
@@ -2130,7 +2166,10 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd)
/* Create a MTD block device name */
#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
- snprintf(dev->rwbuffer, 18, "/dev/smart%dd1", minor);
+ if (partname != NULL)
+ snprintf(dev->rwbuffer, 18, "/dev/smart%d%sd1", minor, partname);
+ else
+ snprintf(dev->rwbuffer, 18, "/dev/smart%dd1", minor);
/* Inode private data is a reference to a struct containing
* the SMART device structure and the root directory number.
@@ -2154,7 +2193,10 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd)
ret = register_blockdriver(dev->rwbuffer, &g_bops, 0, rootdirdev);
#else
- snprintf(dev->rwbuffer, 18, "/dev/smart%d", minor);
+ if (partname != NULL)
+ snprintf(dev->rwbuffer, 18, "/dev/smart%d%s", minor, partname);
+ else
+ snprintf(dev->rwbuffer, 18, "/dev/smart%d", minor);
/* Inode private data is a reference to the SMART device structure */
@@ -2167,6 +2209,7 @@ int smart_initialize(int minor, FAR struct mtd_dev_s *mtd)
kfree(dev->sMap);
kfree(dev->rwbuffer);
kfree(dev);
+ goto errout;
}
/* Do a scan of the device */
diff --git a/nuttx/fs/smartfs/smartfs_smart.c b/nuttx/fs/smartfs/smartfs_smart.c
index 552c0e96e..a1613b899 100644
--- a/nuttx/fs/smartfs/smartfs_smart.c
+++ b/nuttx/fs/smartfs/smartfs_smart.c
@@ -389,6 +389,7 @@ static int smartfs_close(FAR struct file *filep)
/* Remove ourselves from the linked list */
nextfile = fs->fs_head;
+ prevfile = nextfile;
while ((nextfile != sf) && (nextfile != NULL))
{
/* Save the previous file pointer too */
@@ -577,7 +578,7 @@ static int smartfs_sync_internal(struct smartfs_mountpt_s *fs,
if (sf->byteswritten > 0)
{
- fdbg("Syncing sector %d\n", sf->currsector);
+ fvdbg("Syncing sector %d\n", sf->currsector);
/* Read the existing sector used bytes value */
@@ -880,6 +881,7 @@ static off_t smartfs_seek_internal(struct smartfs_mountpt_s *fs,
switch (whence)
{
case SEEK_SET:
+ default:
newpos = offset;
break;
@@ -1034,7 +1036,7 @@ static int smartfs_sync(FAR struct file *filep)
struct inode *inode;
struct smartfs_mountpt_s *fs;
struct smartfs_ofile_s *sf;
- int ret = OK;
+ int ret;
/* Sanity checks */
@@ -1067,7 +1069,6 @@ static int smartfs_sync(FAR struct file *filep)
static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp)
{
- FAR struct smart_mountpt_s *fs;
struct smartfs_ofile_s *sf;
fvdbg("Dup %p->%p\n", oldp, newp);
@@ -1080,10 +1081,8 @@ static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp)
/* Recover our private data from the struct file instance */
- fs = (struct smart_mountpt_s *)oldp->f_inode->i_private;
sf = oldp->f_priv;
- DEBUGASSERT(fs != NULL);
DEBUGASSERT(sf != NULL);
/* Just increment the reference count on the ofile */
diff --git a/nuttx/fs/smartfs/smartfs_utils.c b/nuttx/fs/smartfs/smartfs_utils.c
index a72fef691..30813a44b 100644
--- a/nuttx/fs/smartfs/smartfs_utils.c
+++ b/nuttx/fs/smartfs/smartfs_utils.c
@@ -502,6 +502,8 @@ int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
/* Read the directory */
+ offset = 0xFFFF;
+
#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
while (dirsector != 0xFFFF)
#else
@@ -549,7 +551,8 @@ int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
/* Test if the name matches */
- if (strcmp(entry->name, fs->fs_workbuffer) == 0)
+ if (strncmp(entry->name, fs->fs_workbuffer,
+ fs->fs_llformat.namesize) == 0)
{
/* We found it! If this is the last segment entry,
* then report the entry. If it isn't the last
@@ -571,10 +574,11 @@ int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
direntry->dfirst = dirstack[depth];
if (direntry->name == NULL)
{
- direntry->name = (char *) kmalloc(fs->fs_llformat.namesize);
+ direntry->name = (char *) kmalloc(fs->fs_llformat.namesize+1);
}
- strcpy(direntry->name, entry->name);
+ memset(direntry->name, 0, fs->fs_llformat.namesize + 1);
+ strncpy(direntry->name, entry->name, fs->fs_llformat.namesize);
direntry->datlen = 0;
/* Scan the file's sectors to calculate the length and perform
@@ -734,7 +738,7 @@ int smartfs_createentry(struct smartfs_mountpt_s *fs,
/* Validate the name isn't too long */
- if (strlen(filename) + 1 > fs->fs_llformat.namesize)
+ if (strlen(filename) > fs->fs_llformat.namesize)
{
return -ENAMETOOLONG;
}
@@ -887,13 +891,13 @@ int smartfs_createentry(struct smartfs_mountpt_s *fs,
entry->firstsector = nextsector;
entry->utc = 0;
memset(entry->name, 0, fs->fs_llformat.namesize);
- strncpy(entry->name, filename, fs->fs_llformat.namesize-1);
+ strncpy(entry->name, filename, fs->fs_llformat.namesize);
/* Now write the new entry to the parent directory sector */
readwrite.logsector = psector;
readwrite.offset = offset;
- readwrite.count = sizeof(struct smartfs_entry_header_s) + fs->fs_llformat.namesize;
+ readwrite.count = entrysize;
readwrite.buffer = (uint8_t *) &fs->fs_rwbuffer[offset];
ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
if (ret < 0)
@@ -911,11 +915,11 @@ int smartfs_createentry(struct smartfs_mountpt_s *fs,
direntry->datlen = 0;
if (direntry->name == NULL)
{
- direntry->name = (FAR char *) kmalloc(fs->fs_llformat.namesize);
+ direntry->name = (FAR char *) kmalloc(fs->fs_llformat.namesize+1);
}
- memset(direntry->name, 0, fs->fs_llformat.namesize);
- strncpy(direntry->name, filename, fs->fs_llformat.namesize-1);
+ memset(direntry->name, 0, fs->fs_llformat.namesize+1);
+ strncpy(direntry->name, filename, fs->fs_llformat.namesize);
ret = OK;
diff --git a/nuttx/include/nuttx/fs/ioctl.h b/nuttx/include/nuttx/fs/ioctl.h
index 463b96e18..bd80a7150 100644
--- a/nuttx/include/nuttx/fs/ioctl.h
+++ b/nuttx/include/nuttx/fs/ioctl.h
@@ -193,15 +193,6 @@
* of device memory */
#define MTDIOC_BULKERASE _MTDIOC(0x0003) /* IN: None
* OUT: None */
-#define MTDIOC_GETCAPS _MTDIOC(0x0004) /* IN: None
- * OUT: Capabilities flags */
-#define MTDIOC_SECTERASE _MTDIOC(0x0005) /* IN: Sector number to erase
- * OUT: None */
-#define MTDIOC_BYTEWRITE _MTDIOC(0x0006) /* IN: Pointer to bytewrite structure
- * OUT: None */
-
-#define MTDIOC_CAPS_SECTERASE 0x01
-#define MTDIOC_CAPS_BYTEWRITE 0x02
/* NuttX ARP driver ioctl definitions (see netinet/arp.h) *******************/
diff --git a/nuttx/include/nuttx/mtd.h b/nuttx/include/nuttx/mtd.h
index c4bf4fbee..a528d0003 100644
--- a/nuttx/include/nuttx/mtd.h
+++ b/nuttx/include/nuttx/mtd.h
@@ -83,10 +83,6 @@ struct mtd_geometry_s
uint16_t erasesize; /* Size of one erase blocks -- must be a multiple
* of blocksize. */
size_t neraseblocks; /* Number of erase blocks */
-#ifdef CONFIG_MTD_SUBSECTOR_ERASE
- uint16_t subsectorsize; /* Size of the sub-sector erase block */
- uint16_t nsubsectors; /* Number of sub-sector erase blocks */
-#endif
};
/* The following defines the information for writing bytes to a sector
@@ -179,8 +175,8 @@ extern "C"
* NOTE: Since there may be a number of MTD partition drivers operating on
* the same, underlying FLASH driver, that FLASH driver must be capable
* of enforcing mutually exclusive access to the FLASH device. Without
- * paritions, that mutual exclusing would be provided by the file system
- * abover the FLASH driver.
+ * partitions, that mutual exclusion would be provided by the file system
+ * above the FLASH driver.
*
****************************************************************************/
@@ -213,10 +209,13 @@ int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd);
* minor - The minor device number. The MTD block device will be
* registered as as /dev/mtdsmartN where N is the minor number.
* mtd - The MTD device that supports the FLASH interface.
+ * partname - Optional partition name to append to dev entry, NULL if
+ * not supplied.
*
****************************************************************************/
-int smart_initialize(int minor, FAR struct mtd_dev_s *mtd);
+int smart_initialize(int minor, FAR struct mtd_dev_s *mtd,
+ FAR const char *partname);
/****************************************************************************
* Name: flash_eraseall
diff --git a/nuttx/tools/kconfig2html.c b/nuttx/tools/kconfig2html.c
index f6d21091a..9a089c415 100644
--- a/nuttx/tools/kconfig2html.c
+++ b/nuttx/tools/kconfig2html.c
@@ -2368,7 +2368,8 @@ static char *parse_kconfigfile(FILE *stream, const char *kconfigdir)
{
/* Set token to NULL to skip to the next line */
- error("Unhandled token: %s\n", token);
+ error("File %s/Kconfig Unhandled token: %s\n",
+ kconfigdir, token);
token = NULL;
}
break;