9
0
Fork 0

apps/example/configdata: Unit test for the MTD configuration data driver

This commit is contained in:
Gregory Nutt 2013-11-04 09:05:11 -06:00
parent 56d21b3673
commit cab35aed49
8 changed files with 969 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

11
apps/examples/configdata/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
/Make.dep
/.depend
/.built
/*.asm
/*.obj
/*.rel
/*.lst
/*.sym
/*.adb
/*.lib
/*.src

View File

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

View File

@ -0,0 +1,96 @@
############################################################################
# apps/examples/configdata/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
# 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

View File

@ -0,0 +1,800 @@
/****************************************************************************
* examples/configdata/configdata_main.c
*
* Copyright (C) 2013 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <crc32.h>
#include <debug.h>
#include <nuttx/mtd.h>
#include <nuttx/configdata.h>
#include <nuttx/fs/ioctl.h>
#include <sys/ioctl.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_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;
}