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).
|
data storage. From Ken Pettit (2013-11-1).
|
||||||
* apps/platform/Makefile: Was not dealing with the bin sub-directory
|
* apps/platform/Makefile: Was not dealing with the bin sub-directory
|
||||||
correctly (2013-11-2).
|
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/buttons/Kconfig"
|
||||||
source "$APPSDIR/examples/can/Kconfig"
|
source "$APPSDIR/examples/can/Kconfig"
|
||||||
source "$APPSDIR/examples/cc3000/Kconfig"
|
source "$APPSDIR/examples/cc3000/Kconfig"
|
||||||
|
source "$APPSDIR/examples/configdata/Kconfig"
|
||||||
source "$APPSDIR/examples/cxxtest/Kconfig"
|
source "$APPSDIR/examples/cxxtest/Kconfig"
|
||||||
source "$APPSDIR/examples/dhcpd/Kconfig"
|
source "$APPSDIR/examples/dhcpd/Kconfig"
|
||||||
source "$APPSDIR/examples/elf/Kconfig"
|
source "$APPSDIR/examples/elf/Kconfig"
|
||||||
|
@ -50,6 +50,10 @@ ifeq ($(CONFIG_EXAMPLES_CC3000BASIC),y)
|
|||||||
CONFIGURED_APPS += examples/cc3000
|
CONFIGURED_APPS += examples/cc3000
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_EXAMPLES_CONFIGDATA),y)
|
||||||
|
CONFIGURED_APPS += examples/configdata
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_EXAMPLES_CXXTEST),y)
|
ifeq ($(CONFIG_EXAMPLES_CXXTEST),y)
|
||||||
CONFIGURED_APPS += examples/cxxtest
|
CONFIGURED_APPS += examples/cxxtest
|
||||||
endif
|
endif
|
||||||
|
@ -131,6 +131,11 @@ examples/cc3000
|
|||||||
|
|
||||||
This is a test for the TI CC3000 wireless networking module.
|
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
|
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