diff --git a/ChangeLog.txt b/ChangeLog.txt index 460bb5a8d..537c7d035 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -722,4 +722,6 @@ data storage. From Ken Pettit (2013-11-1). * apps/platform/Makefile: Was not dealing with the bin sub-directory correctly (2013-11-2). + * apps/examples/configdata: A unit test for the MTD configuration + data drriver from Ken Pettit (2013-11-4). diff --git a/examples/Kconfig b/examples/Kconfig index c975c2b36..c7ad1b998 100644 --- a/examples/Kconfig +++ b/examples/Kconfig @@ -7,6 +7,7 @@ source "$APPSDIR/examples/adc/Kconfig" source "$APPSDIR/examples/buttons/Kconfig" source "$APPSDIR/examples/can/Kconfig" source "$APPSDIR/examples/cc3000/Kconfig" +source "$APPSDIR/examples/configdata/Kconfig" source "$APPSDIR/examples/cxxtest/Kconfig" source "$APPSDIR/examples/dhcpd/Kconfig" source "$APPSDIR/examples/elf/Kconfig" diff --git a/examples/Make.defs b/examples/Make.defs index d318a6701..78a3fc273 100644 --- a/examples/Make.defs +++ b/examples/Make.defs @@ -50,6 +50,10 @@ ifeq ($(CONFIG_EXAMPLES_CC3000BASIC),y) CONFIGURED_APPS += examples/cc3000 endif +ifeq ($(CONFIG_EXAMPLES_CONFIGDATA),y) +CONFIGURED_APPS += examples/configdata +endif + ifeq ($(CONFIG_EXAMPLES_CXXTEST),y) CONFIGURED_APPS += examples/cxxtest endif diff --git a/examples/README.txt b/examples/README.txt index 9423dcbcd..c05bffa37 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -131,6 +131,11 @@ examples/cc3000 This is a test for the TI CC3000 wireless networking module. +examples/configdata +^^^^^^^^^^^^^^^^^^^ + + This is a Unit Test for the MTD configuration data driver + examples/cxxtest ^^^^^^^^^^^^^^^^ diff --git a/examples/configdata/.gitignore b/examples/configdata/.gitignore new file mode 100644 index 000000000..fa1ec7579 --- /dev/null +++ b/examples/configdata/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/examples/configdata/Kconfig b/examples/configdata/Kconfig new file mode 100644 index 000000000..49d1d874c --- /dev/null +++ b/examples/configdata/Kconfig @@ -0,0 +1,50 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_CONFIGDATA + bool "Config Data example / unit test" + default n + ---help--- + Enable the Config Data example + +if EXAMPLES_CONFIGDATA + +config EXAMPLES_CONFIGDATA_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_CONFIGDATA_ARCHINIT. In this case, the + initialization logic will call configdata_archinitialize() to obtain + the MTD driver instance. + +config EXAMPLES_CONFIGDATA_NEBLOCKS + int "Number of erase blocks (simulated)" + default 4 + depends on !EXAMPLES_CONFIGDATA_ARCHINIT + ---help--- + When EXAMPLES_CONFIGDATA_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 the MTD RAM device. + + The size of the allocated RAM drive will be: + + RAMMTD_ERASESIZE * EXAMPLES_CONFIGDATA_NEBLOCKS + +config EXAMPLES_CONFIGDATA_NLOOPS + int "Number of test loops" + default 1000 + +config EXAMPLES_CONFIGDATA_VERBOSE + bool "Verbose output" + default n + +config EXAMPLES_CONFIGDATA_SILENT + bool "Silence the test details" + default n + +endif diff --git a/examples/configdata/Makefile b/examples/configdata/Makefile new file mode 100644 index 000000000..e24a59d9a --- /dev/null +++ b/examples/configdata/Makefile @@ -0,0 +1,96 @@ +############################################################################ +# apps/examples/configdata/Makefile +# +# Copyright (C) 2011-2013 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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 + +# CONFIGDATA Unit Test + +ASRCS = +CSRCS = configdata_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep diff --git a/examples/configdata/configdata_main.c b/examples/configdata/configdata_main.c new file mode 100644 index 000000000..d20bffd38 --- /dev/null +++ b/examples/configdata/configdata_main.c @@ -0,0 +1,800 @@ +/**************************************************************************** + * examples/configdata/configdata_main.c + * + * Copyright (C) 2013 Ken Pettit. All rights reserved. + * Author: Ken Pettit + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * 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_CONFIGDATA_ARCHINIT. In this case, the initialization logic + * will call configdata_archinitialize() to obtain the MTD driver instance. + */ + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_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_CONFIGDATA_NEBLOCKS +# define CONFIG_EXAMPLES_CONFIGDATA_NEBLOCKS (256) +# endif + +# define EXAMPLES_CONFIGDATA_BUFSIZE \ + (CONFIG_RAMMTD_ERASESIZE * CONFIG_EXAMPLES_CONFIGDATA_NEBLOCKS) +#endif + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_MAXSIZE +# define CONFIG_EXAMPLES_CONFIGDATA_MAXSIZE 512 +#endif + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES +# define CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES 3000 +#endif + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_NLOOPS +# define CONFIG_EXAMPLES_CONFIGDATA_NLOOPS 100 +#endif + +#define EXAMPLES_CONFIGDATA_REPORT (CONFIG_EXAMPLES_CONFIGDATA_NLOOPS / 20) +#if EXAMPLES_CONFIGDATA_REPORT == 0 +# undef EXAMPLES_CONFIGDATA_REPORT +# define EXAMPLES_CONFIGDATA_REPORT 1 +#endif + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_VERBOSE +# define CONFIG_EXAMPLES_CONFIGDATA_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 configdata_entrydesc_s +{ + uint16_t id; + uint8_t instance; + uint16_t len; + uint32_t crc; + uint8_t deleted; + uint8_t changed; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Pre-allocated simulated flash */ + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_ARCHINIT +static uint8_t g_simflash[EXAMPLES_CONFIGDATA_BUFSIZE<<1]; +#endif + +static uint8_t g_entryimage[CONFIG_EXAMPLES_CONFIGDATA_MAXSIZE]; +static struct configdata_entrydesc_s g_entries[CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES]; +static int g_nentries; +static int g_ndeleted; +static int g_fd; +static int g_ntests, g_nverified; +static int g_ntotalalloc, g_ntotaldelete; + +static struct mallinfo g_mmbefore; +static struct mallinfo g_mmprevious; +static struct mallinfo g_mmafter; + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_CONFIGDATA_ARCHINIT +extern FAR struct mtd_dev_s *configdata_archinitialize(void); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: configdata_memusage + ****************************************************************************/ + +static void configdata_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: configdata_loopmemusage + ****************************************************************************/ + +static void configdata_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"); + configdata_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: configdata_endmemusage + ****************************************************************************/ + +static void configdata_endmemusage(void) +{ +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmafter = mallinfo(); +#else + (void)mallinfo(&g_mmafter); +#endif + message("\nFinal memory usage:\n"); + configdata_showmemusage(&g_mmbefore, &g_mmafter); + + message("\nTotal adds: %d Total deletes : %d\n", + g_ntotalalloc, g_ntotaldelete); + message("Total tests: %d Number passed: %d Failed: %d\n", + g_ntests, g_nverified, g_ntests - g_nverified); +} + +/**************************************************************************** + * Name: configdata_randid + ****************************************************************************/ + +static inline uint16_t configdata_randid(void) +{ + int x; + int value; + +retry: + value = rand() & 0x7FFF; + if (value == 0) + { + value = 100; + } + + /* Ensure we don't have a duplicate id */ + + for (x = 0; x < g_nentries; x++) + { + if (value == g_entries[x].id) + { + goto retry; + } + } + + return value; +} + +/**************************************************************************** + * Name: configdata_randlen + ****************************************************************************/ + +static inline uint16_t configdata_randlen(void) +{ + int value = rand() % CONFIG_EXAMPLES_CONFIGDATA_MAXSIZE; + + if (value == 0) + { + return 1; + } + + return value; +} + +/**************************************************************************** + * Name: configdata_randinstance + ****************************************************************************/ + +static inline uint8_t configdata_randinstance(void) +{ + return rand() & 0xff; +} + +/**************************************************************************** + * Name: configdata_freefile + ****************************************************************************/ + +static void configdata_freeentry(FAR struct configdata_entrydesc_s *entry) +{ + memset(entry, 0, sizeof(struct configdata_entrydesc_s)); +} + +/**************************************************************************** + * Name: configdata_wrentry + ****************************************************************************/ + +static inline int configdata_wrentry(FAR struct configdata_entrydesc_s *entry) +{ + size_t x; + int ret; + struct config_data_s config; + + /* Create a random entry */ + + entry->id = configdata_randid(); + entry->instance = configdata_randinstance(); + entry->len = configdata_randlen(); + + /* Write some random data to the entry */ + + for (x = 0; x < entry->len; x++) + { + g_entryimage[x] = rand() & 0xFF; + } + + /* Calculate the crc32 for the data */ + + entry->crc = crc32(g_entryimage, entry->len); + + /* Write the entry to the /dev/config device */ + + config.id = entry->id; + config.instance = entry->instance; + config.len = entry->len; + config.configdata = g_entryimage; + ret = ioctl(g_fd, CFGDIOC_SETCONFIG, (unsigned long) &config); + if (ret < 0) + { + entry->id = 0; + entry->len = 0; + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: configdata_fillconfig + ****************************************************************************/ + +static int configdata_fillconfig(void) +{ + FAR struct configdata_entrydesc_s *entry; + int ret; + int i; + + /* Create a file for each unused file structure */ + + for (i = 0; i < CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES; i++) + { + entry = &g_entries[i]; + if (entry->id == 0) + { + ret = configdata_wrentry(entry); + if (ret < 0) + { +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message(" /dev/config full\n"); +#endif + return ERROR; + } + +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message(" Created entry %04X, %d Len=%d\n", + entry->id, entry->instance, entry->len); +#endif + g_nentries++; + g_ntotalalloc++; + } + } + + return OK; +} + +/**************************************************************************** + * Name: configdata_rdentry + ****************************************************************************/ + +static inline int configdata_rdentry(FAR struct configdata_entrydesc_s *entry) +{ + struct config_data_s config; + uint32_t crc; + int ret; + + /* Read the config entry from /dev/config */ + + config.id = entry->id; + config.instance = entry->instance; + config.len = entry->len; + config.configdata = g_entryimage; + ret = ioctl(g_fd, CFGDIOC_GETCONFIG, (unsigned long) &config); + if (ret < 0) + { + return ERROR; + } + + /* Verify the file image CRC */ + + crc = crc32(g_entryimage, entry->len); + if (crc != entry->crc) + { + message("ERROR: Bad CRC: %d vs %d\n", crc, entry->crc); + message(" Entry id: %04X\n", entry->id); + message(" Entry size: %d\n", entry->len); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: configdata_verifyconfig + ****************************************************************************/ + +static int configdata_verifyconfig(void) +{ + FAR struct configdata_entrydesc_s *entry; + int ret; + int err = OK; + int i; + static int iteration = 0; + + /* Create a file for each unused file structure */ + + iteration++; + for (i = 0; i < CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES; i++) + { + entry = &g_entries[i]; + if (entry->id != 0) + { + g_ntests++; + ret = configdata_rdentry(entry); + if (ret < 0) + { + /* Check if this entry has been deleted */ + + if (entry->deleted) + { + /* Good, it wasn't found (as it shouldn't be) */ + + g_nverified++; +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message(" Verified delete %04X, %d\n", entry->id, + entry->instance); +#endif + } + else + { + message("ERROR: Failed to read an entry: %d\n", i); + message(" Entry id: %04X\n", entry->id); + message(" Entry size: %d\n", entry->len); + err = ERROR; + } + } + else + { + /* Check if this entry has been deleted and should report an error */ + + if (entry->deleted) + { + message("ERROR: Succesffully read a deleted entry\n"); + message(" Entry id: %04X\n", entry->id); + message(" Entry size: %d\n", entry->len); + err = ERROR; + } + else + { + g_nverified++; +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message(" Verifed entry %04X, %d\n", entry->id, entry->instance); +#endif + } + } + } + } + + return err; +} + +/**************************************************************************** + * Name: configdata_delentries + ****************************************************************************/ + +static int configdata_delentries(void) +{ + FAR struct configdata_entrydesc_s *entry; + struct config_data_s hdr; + int ndel; + int ret; + int i; + int j; + + /* Are there any files to be deleted? */ + + int nentries = g_nentries - g_ndeleted; + if (nentries < 1) + { + return 0; + } + + /* Yes... How many files should we delete? */ + + ndel = (rand() % nentries) + 1; + + /* Now pick which files to delete */ + + for (i = 0; i < ndel; i++) + { + /* Guess a file index */ + + int ndx = (rand() % (g_nentries - g_ndeleted)); + + /* And delete the next undeleted file after that random index */ + + for (j = ndx + 1; j != ndx;) + { + entry = &g_entries[j]; + if (entry->id && !entry->deleted) + { + hdr.id = entry->id; + hdr.instance = entry->instance; + hdr.len = 0; + ret = ioctl(g_fd, CFGDIOC_SETCONFIG, (unsigned long) &hdr); + if (ret < 0) + { + message("ERROR: Delete %d failed: %d\n", i+1, errno); + message(" Entry id: %04X\n", entry->id); + message(" Entry size: %d\n", entry->len); + message(" Entry index: %d\n", j); + } + else + { +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message(" Deleted entry %04X\n", entry->id); +#endif + entry->deleted = true; + g_ndeleted++; + g_ntotaldelete++; + break; + } + } + + /* Increment the index and test for wrap-around */ + + if (++j >= CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES) + { + j = 0; + } + } + } + + return OK; +} + +/**************************************************************************** + * Name: configdata_getnextdeleted + ****************************************************************************/ + +static int configdata_getnextdeleted(void) +{ + int x; + int nextdeleted = -1; + + /* Find next deleted entry */ + + for (x = 0; x < CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES; x++) + { + if (g_entries[x].deleted) + { + nextdeleted = x; + break; + } + } + + return nextdeleted; +} + +/**************************************************************************** + * Name: configdata_cleardeleted + ****************************************************************************/ + +static int configdata_cleardeleted(void) +{ + int nextdeleted; + int x; + + while ((nextdeleted = configdata_getnextdeleted()) != -1) + { + /* Find next non-deleted entry after the deleted one */ + + for (x = nextdeleted + 1; x < CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES; x++) + { + if (g_entries[x].id && !g_entries[x].deleted) + { + break; + } + } + + /* Test if an non-deleted entry found */ + + if (x < CONFIG_EXAMPLES_CONFIGDATA_MAXENTRIES) + { + /* Move this entry to the deleted entry location */ + +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message(" Overwrite entry %d, OLD=%04X NEW=%04X\n", + nextdeleted, g_entries[nextdeleted].id, g_entries[x].id); +#endif + + g_entries[nextdeleted] = g_entries[x]; + g_entries[x].id = 0; + } + else + { + /* Just remove the entry */ + g_entries[nextdeleted].id = 0; + g_entries[nextdeleted].deleted = FALSE; + } + } + + g_nentries -= g_ndeleted; + g_ndeleted = 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: configdata_main + ****************************************************************************/ + +int configdata_main(int argc, char *argv[]) +{ + unsigned int i; + int ret; + FAR struct mtd_dev_s *mtd; + + /* Seed the random number generated */ + + srand(0x93846); + + /* Create and initialize a RAM MTD device instance */ + +#ifdef CONFIG_EXAMPLES_CONFIGDATA_ARCHINIT + mtd = configdata_archinitialize(); +#else +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message("Creating %d byte RAM drive\n", EXAMPLES_CONFIGDATA_BUFSIZE); +#endif + mtd = rammtd_initialize(g_simflash, EXAMPLES_CONFIGDATA_BUFSIZE); +#endif + if (!mtd) + { + message("ERROR: Failed to create RAM MTD instance\n"); + msgflush(); + exit(1); + } + + /* Initialize to provide CONFIGDATA on an MTD interface */ + +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message("Registering /dev/config device\n"); +#endif + MTD_IOCTL(mtd, MTDIOC_BULKERASE, 0); + ret = mtdconfig_register(mtd); + if (ret < 0) + { + message("ERROR: /dev/config registration failed: %d\n", -ret); + msgflush(); + exit(2); + } + + /* Zero out our entry array */ + + memset(g_entries, 0, sizeof(g_entries)); + + /* Open the /dev/config device */ + + g_fd = open("/dev/config", O_RDOK); + if (g_fd == -1) + { + message("ERROR: Failed to open /dev/config %d\n", -errno); + msgflush(); + exit(2); + } + + /* Initialize the before memory values */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmbefore = mallinfo(); +#else + (void)mallinfo(&g_mmbefore); +#endif + + /* Loop seveal times ... create some config data items, delete them + * randomly, verify them randomly, add new config items. + */ + + g_ntests = g_nverified = 0; + g_ntotaldelete = g_ntotalalloc = 0; + +#if CONFIG_EXAMPLES_CONFIGDATA_NLOOPS == 0 + for (i = 0; ; i++) +#else + for (i = 1; i <= CONFIG_EXAMPLES_CONFIGDATA_NLOOPS; i++) +#endif + { + /* Write config data to the /dev/config device until either (1) all of the + * open file structures are utilized or until (2) CONFIGDATA reports an error + * (hopefully that the /dev/config device is full) + */ + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT + message("\n=== FILLING %d =============================\n", i); +#endif + ret = configdata_fillconfig(); +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT + message("Filled /dev/config\n"); + message(" Number of entries: %d\n", g_nentries); +#endif + + /* Verify all files entries to FLASH */ + + ret = configdata_verifyconfig(); + if (ret < 0) + { + message("ERROR: Failed to verify partition\n"); + message(" Number of entries: %d\n", g_nentries); + } + else + { +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message("Verified!\n"); + message(" Number of entries: %d\n", g_nentries); +#endif +#endif + } + + /* Delete some entries */ + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT + message("\n=== DELETING %d ============================\n", i); +#endif + ret = configdata_delentries(); + if (ret < 0) + { + message("ERROR: Failed to delete enries\n"); + message(" Number of entries: %d\n", g_nentries); + message(" Number deleted: %d\n", g_ndeleted); + } + else + { +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT + message("Deleted some enries\n"); + message(" Number of entries: %d\n", g_nentries); + message(" Number deleted: %d\n", g_ndeleted); +#endif + } + + /* Verify all files written to FLASH */ + + ret = configdata_verifyconfig(); + if (ret < 0) + { + message("ERROR: Failed to verify partition\n"); + message(" Number of entries: %d\n", g_nentries); + message(" Number deleted: %d\n", g_ndeleted); + } + else + { +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT +#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 + message("Verified!\n"); + message(" Number of entries: %d\n", g_nentries); + message(" Number deleted: %d\n", g_ndeleted); +#endif +#endif + } + + /* Clear deleted entries */ + + configdata_cleardeleted(); + + /* Show memory usage */ + +#ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT + configdata_loopmemusage(); + msgflush(); +#else + if ((i % EXAMPLES_CONFIGDATA_REPORT) == 0) + { + message("%d\n", i); + msgflush(); + } +#endif + } + + /* Delete all files then show memory usage again */ + + //configdata_delallfiles(); + configdata_endmemusage(); + msgflush(); + return 0; +}