Add an example to test MTD R/W buffering
This commit is contained in:
parent
12d471553c
commit
dbb64323a4
@ -26,6 +26,7 @@ source "$APPSDIR/examples/mm/Kconfig"
|
||||
source "$APPSDIR/examples/modbus/Kconfig"
|
||||
source "$APPSDIR/examples/mount/Kconfig"
|
||||
source "$APPSDIR/examples/mtdpart/Kconfig"
|
||||
source "$APPSDIR/examples/mtdrwb/Kconfig"
|
||||
source "$APPSDIR/examples/netpkt/Kconfig"
|
||||
source "$APPSDIR/examples/nettest/Kconfig"
|
||||
source "$APPSDIR/examples/nrf24l01_term/Kconfig"
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
SUBDIRS = adc buttons can cc3000 cpuhog cxxtest dhcpd discover elf
|
||||
SUBDIRS += flash_test ftpc ftpd hello helloxx hidkbd igmp i2schar json
|
||||
SUBDIRS += keypadtest lcdrw mm modbus mount mtdpart netpkt nettest
|
||||
SUBDIRS += keypadtest lcdrw mm modbus mount mtdpart mtdrwb netpkt nettest
|
||||
SUBDIRS += nrf24l01_term nsh null nx nxterm nxffs nxflat nxhello nximage
|
||||
SUBDIRS += nxlines nxtext ostest pashello pipe poll posix_spawn pwm qencoder
|
||||
SUBDIRS += random relays rgmp romfs sendmail serialblaster serloop serialrx
|
||||
@ -54,7 +54,7 @@ CNTXTDIRS = pwm
|
||||
|
||||
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
|
||||
CNTXTDIRS += adc can cc3000 cpuhog cxxtest dhcpd discover flash_test ftpd
|
||||
CNTXTDIRS += hello helloxx i2schar json keypadtestmodbus lcdrw mtdpart
|
||||
CNTXTDIRS += hello helloxx i2schar json keypadtestmodbus lcdrw mtdpart mtdrwb
|
||||
CNTXTDIRS += netpkt nettest nx nxhello nximage nxlines nxtext nrf24l01_term
|
||||
CNTXTDIRS += ostest random relays qencoder serialblasterslcd serialrx
|
||||
CNTXTDIRS += smart_test tcpecho telnetd tiff touchscreen usbterm watchdog
|
||||
|
@ -661,6 +661,30 @@ examples/mtdpart
|
||||
* CONFIG_EXAMPLES_MTDPART_NEBLOCKS - This value gives the nubmer of erase
|
||||
blocks in MTD RAM device.
|
||||
|
||||
examples/mtdrwb
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This examples provides a simple test of MTD Read-Ahead/Write buffering
|
||||
logic.
|
||||
|
||||
* CONFIG_EXAMPLES_MTDRWB - Enables the MTD R/W buffering test example
|
||||
* CONFIG_EXAMPLES_MTDRWB_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_MTDRWB_ARCHINIT. In
|
||||
this case, the initialization logic will call mtdrwb_archinitialize()
|
||||
to obtain the MTD driver instance.
|
||||
|
||||
When CONFIG_EXAMPLES_MTDRWB_ARCHINIT is not defined, this test will use
|
||||
the RAM MTD device at drivers/mtd/rammtd.c to simulate FLASH. The size of
|
||||
the allocated RAM drive will be: CONFIG_EXMPLES_RAMMTD_ERASESIZE *
|
||||
CONFIG_EXAMPLES_MTDRWB_NEBLOCKS
|
||||
|
||||
* CONFIG_EXAMPLES_MTDRWB_ERASESIZE - This value gives the size of one
|
||||
erase block in the MTD RAM device. This must exactly match the default
|
||||
configuration in drivers/mtd/rammtd.c!
|
||||
* CONFIG_EXAMPLES_MTDRWB_NEBLOCKS - This value gives the nubmer of erase
|
||||
blocks in MTD RAM device.
|
||||
|
||||
examples/netpkt
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
11
examples/mtdrwb/.gitignore
vendored
Normal file
11
examples/mtdrwb/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/Make.dep
|
||||
/.depend
|
||||
/.built
|
||||
/*.asm
|
||||
/*.obj
|
||||
/*.rel
|
||||
/*.lst
|
||||
/*.sym
|
||||
/*.adb
|
||||
/*.lib
|
||||
/*.src
|
67
examples/mtdrwb/Kconfig
Normal file
67
examples/mtdrwb/Kconfig
Normal file
@ -0,0 +1,67 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see misc/tools/kconfig-language.txt.
|
||||
#
|
||||
|
||||
config EXAMPLES_MTDRWB
|
||||
bool "MTD R/W buffer test"
|
||||
default n
|
||||
depends on (MTD_WRBUFFER || MTD_READAHEAD) && !BUILD_PROTECTED && !BUILD_KERNEL
|
||||
---help---
|
||||
Enable the MTD R/W buffer test example.
|
||||
|
||||
NOTE: This example uses some internal NuttX interfaces and, hence,
|
||||
is not available in the kernel build.
|
||||
|
||||
if EXAMPLES_MTDRWB
|
||||
|
||||
config EXAMPLES_MTDRWB_PROGNAME
|
||||
string "Program name"
|
||||
default "mtdrwb"
|
||||
depends on BUILD_KERNEL
|
||||
---help---
|
||||
This is the name of the program that will be use when the NSH ELF
|
||||
program is installed.
|
||||
|
||||
config EXAMPLES_MTDRWB_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_MTDRWB_ARCHINIT. In this case, the
|
||||
initialization logic will call mtdrwb_archinitialize() to obtain
|
||||
the MTD driver instance.
|
||||
|
||||
if !EXAMPLES_MTDRWB_ARCHINIT
|
||||
|
||||
config EXAMPLES_MTDRWB_ERASESIZE
|
||||
int "Size of one erase blocks (simulated)"
|
||||
default 4096
|
||||
depends on !EXAMPLES_MTDRWB_ARCHINIT
|
||||
---help---
|
||||
When EXAMPLES_MTDRWB_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 size of one erase
|
||||
simulated erase blocks one MTD RAM device.
|
||||
|
||||
The size of the allocated RAM drive will be:
|
||||
|
||||
EXAMPLES_MTDRWB_ERASESIZE * EXAMPLES_MTDRWB_NEBLOCKS
|
||||
|
||||
config EXAMPLES_MTDRWB_NEBLOCKS
|
||||
int "Number of erase blocks (simulated)"
|
||||
default 32
|
||||
depends on !EXAMPLES_MTDRWB_ARCHINIT
|
||||
---help---
|
||||
When EXAMPLES_MTDRWB_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 number of erase
|
||||
blocks in MTD RAM device.
|
||||
|
||||
The size of the allocated RAM drive will be:
|
||||
|
||||
EXAMPLES_MTDRWB_ERASESIZE * EXAMPLES_MTDRWB_NEBLOCKS
|
||||
|
||||
endif # EXAMPLES_MTDRWB_ARCHINIT
|
||||
endif # EXAMPLES_MTDRWB
|
124
examples/mtdrwb/Makefile
Executable file
124
examples/mtdrwb/Makefile
Executable file
@ -0,0 +1,124 @@
|
||||
############################################################################
|
||||
# apps/examplex/mtdrwb/Makefile
|
||||
#
|
||||
# Copyright (C) 2014 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
|
||||
|
||||
# Hello, World! Example
|
||||
|
||||
ASRCS =
|
||||
CSRCS =
|
||||
MAINSRC = mtdrwb_main.c
|
||||
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||
MAINOBJ = $(MAINSRC:.c=$(OBJEXT))
|
||||
|
||||
SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
|
||||
OBJS = $(AOBJS) $(COBJS)
|
||||
|
||||
ifneq ($(CONFIG_BUILD_KERNEL),y)
|
||||
OBJS += $(MAINOBJ)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
|
||||
BIN = ..\..\libapps$(LIBEXT)
|
||||
else
|
||||
ifeq ($(WINTOOL),y)
|
||||
BIN = ..\\..\\libapps$(LIBEXT)
|
||||
else
|
||||
BIN = ../../libapps$(LIBEXT)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(WINTOOL),y)
|
||||
INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}"
|
||||
else
|
||||
INSTALL_DIR = $(BIN_DIR)
|
||||
endif
|
||||
|
||||
CONFIG_EXAMPLES_MTDRWB_PROGNAME ?= mtdrwb$(EXEEXT)
|
||||
PROGNAME = $(CONFIG_XYZ_PROGNAME)
|
||||
|
||||
ROOTDEPPATH = --dep-path .
|
||||
|
||||
# Common build
|
||||
|
||||
VPATH =
|
||||
|
||||
all: .built
|
||||
.PHONY: clean depend distclean
|
||||
|
||||
$(AOBJS): %$(OBJEXT): %.S
|
||||
$(call ASSEMBLE, $<, $@)
|
||||
|
||||
$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c
|
||||
$(call COMPILE, $<, $@)
|
||||
|
||||
.built: $(OBJS)
|
||||
$(call ARCHIVE, $(BIN), $(OBJS))
|
||||
@touch .built
|
||||
|
||||
ifeq ($(CONFIG_BUILD_KERNEL),y)
|
||||
$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ)
|
||||
@echo "LD: $(PROGNAME)"
|
||||
$(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS)
|
||||
$(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME)
|
||||
|
||||
install: $(BIN_DIR)$(DELIM)$(PROGNAME)
|
||||
|
||||
else
|
||||
install:
|
||||
|
||||
endif
|
||||
|
||||
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
|
443
examples/mtdrwb/mtdrwb_main.c
Normal file
443
examples/mtdrwb/mtdrwb_main.c
Normal file
@ -0,0 +1,443 @@
|
||||
/****************************************************************************
|
||||
* examplex/mtdrwb/mtdrwb_main.c
|
||||
*
|
||||
* Copyright (C) 2014 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_MTDRWB
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#if !defined(CONFIG_MTD_WRBUFFER) && !defined(CONFIG_MTD_READAHEAD)
|
||||
# error CONFIG_MTD_WRBUFFER or CONFIG_MTD_READAHEAD must be selected
|
||||
#endif
|
||||
|
||||
/* 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_MTDRWB_ARCHINIT. In this case, the initialization logic
|
||||
* will call mtdrwb_archinitialize() to obtain the MTD driver instance.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_MTDRWB_ARCHINIT
|
||||
|
||||
/* Make sure that the RAM MTD driver is enabled */
|
||||
|
||||
# ifndef CONFIG_RAMMTD
|
||||
# error "CONFIG_RAMMTD is required without CONFIG_EXAMPLES_MTDRWB_ARCHINIT"
|
||||
# endif
|
||||
|
||||
/* This must exactly match the default configuration in drivers/mtd/rammtd.c */
|
||||
|
||||
# ifndef CONFIG_RAMMTD_ERASESIZE
|
||||
# define CONFIG_RAMMTD_ERASESIZE 4096
|
||||
# endif
|
||||
|
||||
/* Given the ERASESIZE, CONFIG_EXAMPLES_MTDRWB_NEBLOCKS will determine the
|
||||
* size of the RAM allocation needed.
|
||||
*/
|
||||
|
||||
# ifndef CONFIG_EXAMPLES_MTDRWB_NEBLOCKS
|
||||
# define CONFIG_EXAMPLES_MTDRWB_NEBLOCKS (32)
|
||||
# endif
|
||||
|
||||
# undef MTDRWB_BUFSIZE
|
||||
# define MTDRWB_BUFSIZE \
|
||||
(CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_MTDRWB_NEBLOCKS)
|
||||
|
||||
#endif
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
#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 mtdweb_filedesc_s
|
||||
{
|
||||
FAR char *name;
|
||||
bool deleted;
|
||||
size_t len;
|
||||
uint32_t crc;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* Pre-allocated simulated flash */
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_MTDRWB_ARCHINIT
|
||||
static uint8_t g_simflash[MTDRWB_BUFSIZE];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* External Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_MTDRWB_ARCHINIT
|
||||
extern FAR struct mtd_dev_s *mtdrwb_archinitialize(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtdrwb_main
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
int main(int argc, FAR char *argv[])
|
||||
#else
|
||||
int mtdrwb_main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
FAR struct mtd_dev_s *mtdraw;
|
||||
FAR struct mtd_dev_s *mtdrwb;
|
||||
FAR struct mtd_geometry_s geo;
|
||||
FAR uint32_t *buffer;
|
||||
ssize_t nbytes;
|
||||
off_t nblocks;
|
||||
off_t offset;
|
||||
off_t check;
|
||||
off_t sectoff;
|
||||
off_t seekpos;
|
||||
unsigned int blkpererase;
|
||||
int fd;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
int ret;
|
||||
|
||||
/* Create and initialize a RAM MTD FLASH driver instance */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_MTDRWB_ARCHINIT
|
||||
mtdraw = mtdrwb_archinitialize();
|
||||
#else
|
||||
mtdraw = rammtd_initialize(g_simflash, MTDRWB_BUFSIZE);
|
||||
#endif
|
||||
if (!mtdraw)
|
||||
{
|
||||
message("ERROR: Failed to create RAM MTD instance\n");
|
||||
msgflush();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to erase the entire FLASH part */
|
||||
|
||||
ret = mtdraw->ioctl(mtdraw, MTDIOC_BULKERASE, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
message("ERROR: MTDIOC_BULKERASE ioctl failed: %d\n", ret);
|
||||
}
|
||||
|
||||
/* Initialize to support buffering on the MTD device */
|
||||
|
||||
mtdrwb = mtd_rwb_initialize(mtdraw);
|
||||
if (!mtdrwb)
|
||||
{
|
||||
message("ERROR: Failed to create RAM MTD R/W buffering\n");
|
||||
msgflush();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* Initialize to provide an FTL block driver on the MTD FLASH interface.
|
||||
*
|
||||
* NOTE: We could just skip all of this FTL and BCH stuff. We could
|
||||
* instead just use the MTD drivers bwrite and bread to perform this
|
||||
* test. Creating the character drivers, however, makes this test more
|
||||
* interesting.
|
||||
*/
|
||||
|
||||
ret = ftl_initialize(0, mtdrwb);
|
||||
if (ret < 0)
|
||||
{
|
||||
message("ERROR: ftl_initialize /dev/mtdblock0 failed: %d\n", ret);
|
||||
msgflush();
|
||||
exit(3);
|
||||
}
|
||||
|
||||
/* Now create a character device on the block device */
|
||||
|
||||
ret = bchdev_register("/dev/mtdblock0", "/dev/mtd0", false);
|
||||
if (ret < 0)
|
||||
{
|
||||
message("ERROR: bchdev_register /dev/mtd0 failed: %d\n", ret);
|
||||
msgflush();
|
||||
exit(4);
|
||||
}
|
||||
|
||||
/* Get the geometry of the FLASH device */
|
||||
|
||||
ret = mtdrwb->ioctl(mtdrwb, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: mtdrwb->ioctl failed: %d\n", ret);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
message("Flash Geometry:\n");
|
||||
message(" blocksize: %lu\n", (unsigned long)geo.blocksize);
|
||||
message(" erasesize: %lu\n", (unsigned long)geo.erasesize);
|
||||
message(" neraseblocks: %lu\n", (unsigned long)geo.neraseblocks);
|
||||
|
||||
/* Allocate a buffer */
|
||||
|
||||
buffer = (FAR uint32_t *)malloc(geo.blocksize);
|
||||
if (!buffer)
|
||||
{
|
||||
message("ERROR: failed to allocate a sector buffer\n");
|
||||
msgflush();
|
||||
exit(6);
|
||||
}
|
||||
|
||||
/* Open the MTD FLASH character driver for writing */
|
||||
|
||||
fd = open("/dev/mtd0", O_WRONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
message("ERROR: open /dev/mtd0 failed: %d\n", errno);
|
||||
msgflush();
|
||||
exit(7);
|
||||
}
|
||||
|
||||
/* Now write the offset into every block */
|
||||
|
||||
message("Initializing media:\n");
|
||||
|
||||
offset = 0;
|
||||
for (i = 0; i < geo.neraseblocks; i++)
|
||||
{
|
||||
for (j = 0; j < blkpererase; j++)
|
||||
{
|
||||
/* Fill the block with the offset */
|
||||
|
||||
for (k = 0; k < geo.blocksize / sizeof(uint32_t); k++)
|
||||
{
|
||||
buffer[k] = offset;
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
/* And write it using the character driver */
|
||||
|
||||
nbytes = write(fd, buffer, geo.blocksize);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
message("ERROR: write to /dev/mtd0 failed: %d\n", errno);
|
||||
msgflush();
|
||||
exit(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
/* Open the MTD character driver for writing */
|
||||
|
||||
fd = open("/dev/mtd0", O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
message("ERROR: open /dev/mtd0 failed: %d\n", errno);
|
||||
msgflush();
|
||||
exit(9);
|
||||
}
|
||||
|
||||
/* Now verify the offset in every block */
|
||||
|
||||
check = offset;
|
||||
sectoff = 0;
|
||||
|
||||
for (j = 0; j < nblocks; j++)
|
||||
{
|
||||
#if 0 /* Too much */
|
||||
message(" block=%u offset=%lu\n", j, (unsigned long) check);
|
||||
#endif
|
||||
/* Seek to the next read position */
|
||||
|
||||
seekpos = lseek(fd, sectoff, SEEK_SET);
|
||||
if (seekpos != sectoff)
|
||||
{
|
||||
message("ERROR: lseek to offset %ld failed: %d\n",
|
||||
(unsigned long)sectoff, errno);
|
||||
msgflush();
|
||||
exit(10);
|
||||
}
|
||||
|
||||
/* Read the next block into memory */
|
||||
|
||||
nbytes = read(fd, buffer, geo.blocksize);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
message("ERROR: read from /dev/mtd0 failed: %d\n", errno);
|
||||
msgflush();
|
||||
exit(11);
|
||||
}
|
||||
else if (nbytes == 0)
|
||||
{
|
||||
message("ERROR: Unexpected end-of file in /dev/mtd0\n");
|
||||
msgflush();
|
||||
exit(12);
|
||||
}
|
||||
else if (nbytes != geo.blocksize)
|
||||
{
|
||||
message("ERROR: Unexpected read size from /dev/mtd0 : %ld\n",
|
||||
(unsigned long)nbytes);
|
||||
msgflush();
|
||||
exit(13);
|
||||
}
|
||||
|
||||
/* Since we forced the size of the partition to be an even number
|
||||
* of erase blocks, we do not expect to encounter the end of file
|
||||
* indication.
|
||||
*/
|
||||
|
||||
else if (nbytes == 0)
|
||||
{
|
||||
message("ERROR: Unexpected end of file on /dev/mtd0\n");
|
||||
msgflush();
|
||||
exit(14);
|
||||
}
|
||||
|
||||
/* This is not expected at all */
|
||||
|
||||
else if (nbytes != geo.blocksize)
|
||||
{
|
||||
message("ERROR: Short read from /dev/mtd0 failed: %lu\n",
|
||||
(unsigned long)nbytes);
|
||||
msgflush();
|
||||
exit(15);
|
||||
}
|
||||
|
||||
/* Verify the offsets in the block */
|
||||
|
||||
for (k = 0; k < geo.blocksize / sizeof(uint32_t); k++)
|
||||
{
|
||||
if (buffer[k] != check)
|
||||
{
|
||||
message("ERROR: Bad offset %lu, expected %lu\n",
|
||||
(long)buffer[k], (long)check);
|
||||
msgflush();
|
||||
exit(16);
|
||||
}
|
||||
|
||||
/* Invert the value to indicate that we have verified
|
||||
* this value.
|
||||
*/
|
||||
|
||||
buffer[k] = ~check;
|
||||
check += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/* Seek to the next write position */
|
||||
|
||||
seekpos = lseek(fd, sectoff, SEEK_SET);
|
||||
if (seekpos != sectoff)
|
||||
{
|
||||
message("ERROR: lseek to offset %ld failed: %d\n",
|
||||
(unsigned long)sectoff, errno);
|
||||
msgflush();
|
||||
exit(17);
|
||||
}
|
||||
|
||||
/* Now write the block back to FLASH with the modified value */
|
||||
|
||||
nbytes = write(fd, buffer, geo.blocksize);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
message("ERROR: write to /dev/mtd0 failed: %d\n", errno);
|
||||
msgflush();
|
||||
exit(18);
|
||||
}
|
||||
else if (nbytes != geo.blocksize)
|
||||
{
|
||||
message("ERROR: Unexpected write size to /dev/mtd0 : %ld\n",
|
||||
(unsigned long)nbytes);
|
||||
msgflush();
|
||||
exit(19);
|
||||
}
|
||||
|
||||
/* Get the offset to the next block */
|
||||
|
||||
sectoff += geo.blocksize;
|
||||
}
|
||||
|
||||
/* Try reading one more time. We should get the end of file */
|
||||
|
||||
nbytes = read(fd, buffer, geo.blocksize);
|
||||
if (nbytes != 0)
|
||||
{
|
||||
message("ERROR: Expected end-of-file from /dev/mtd0 failed: %d %d\n",
|
||||
nbytes, errno);
|
||||
msgflush();
|
||||
exit(20);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
/* And exit without bothering to clean up */
|
||||
|
||||
message("PASS: Everything looks good\n");
|
||||
msgflush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_EXAMPLES_MTDRWB */
|
Loading…
Reference in New Issue
Block a user