apps/example/configdata: Unit test for the MTD configuration data driver
This commit is contained in:
parent
dc7f894963
commit
b8177768eb
@ -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).
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
examples/configdata/.gitignore
vendored
Normal file
11
examples/configdata/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/Make.dep
|
||||
/.depend
|
||||
/.built
|
||||
/*.asm
|
||||
/*.obj
|
||||
/*.rel
|
||||
/*.lst
|
||||
/*.sym
|
||||
/*.adb
|
||||
/*.lib
|
||||
/*.src
|
50
examples/configdata/Kconfig
Normal file
50
examples/configdata/Kconfig
Normal 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
|
96
examples/configdata/Makefile
Normal file
96
examples/configdata/Makefile
Normal 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
|
800
examples/configdata/configdata_main.c
Normal file
800
examples/configdata/configdata_main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user