9
0
Fork 0

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).

This commit is contained in:
Gregory Nutt 2013-05-03 12:52:33 -06:00
parent 2567deb033
commit 1092e4b163
28 changed files with 1820 additions and 457 deletions

View File

@ -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).

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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
^^^^^^^^^^^^^^^^^^^

View File

@ -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

12
apps/examples/smart/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
Make.dep
.depend
.built
*.swp
*.asm
*.rel
*.lst
*.sym
*.adb
*.lib
*.src

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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).

View File

@ -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>
@ -2567,6 +2580,38 @@ nsh>
<td><br></td>
<td><hr></td>
</tr>
<tr>
<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>

View File

@ -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---
The activity weight to report to the power management subsystem when a button is pressed.
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---
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

View File

@ -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
========

View File

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

View File

@ -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

View File

@ -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
========

View File

@ -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

View File

@ -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,9 +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 */
/* Send the "Sector Erase (SE)" or Sub-Sector Erase (SSE) instruction
* that was passed in as the erase type.
*/
(void)SPI_SEND(priv->dev, M25P_SE);
(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
@ -521,53 +536,6 @@ static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector)
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.
*/
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);
/* 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");
}
#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;
m25p_sectorerase(priv, startblock);
/* 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;
/* 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;
}
@ -817,6 +828,78 @@ static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
return 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;

View File

@ -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;

View File

@ -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)
{
@ -328,6 +328,34 @@ static ssize_t ram_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
return nblocks;
}
/****************************************************************************
* 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;

View File

@ -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;
@ -568,6 +541,74 @@ static int smart_setsectorsize(struct smart_struct_s *dev, uint16_t size)
return OK;
}
/****************************************************************************
* 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
*
@ -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 */

View File

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

View File

@ -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;

View File

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

View File

@ -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

View File

@ -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;