diff --git a/Documentation/applications/testing/nand_sim/index.rst b/Documentation/applications/testing/nand_sim/index.rst
new file mode 100644
index 00000000000..cf5fb2cee84
--- /dev/null
+++ b/Documentation/applications/testing/nand_sim/index.rst
@@ -0,0 +1,171 @@
+======================================
+``nand`` - NAND Flash Device Simulator
+======================================
+
+In order to test the filesystems that work with NAND flash devices in a
+simulator, this exists to provide a virtual NAND flash device, along with its
+driver, to allow manual (or scripted) testing, as well as to provide an
+option to log the various actions performed under-the-hood along with the
+state of the device, which includes the read, write and erase counts of each
+page in the device.
+
+Structure of NAND Flash
+=======================
+
+Most NAND flashes share a common interface, specified by the
+`Open NAND Flash Interface (ONFI) `_.
+
+The important part from it, required in this context, is that a NAND Flash is
+divided into a lot of blocks. And each blocks are divided into a lot of
+pages.
+
+Here's the peculiar bit. If you want to erase a page, you need to erase
+the *entire* block that it is part of, ie. blocks are the smallest erasable
+units in a NAND flash. However, a page is the smallest unit to which you can
+write data, or read data from.
+
+Why would you need erase operation? The Program/ Erase (P/E) cycle states
+that a page (and thus its block) need to be erased first before data can be
+written to it (Erase-Before-Write).
+
+Each page has a data area, and a spare area. Depending on the data area's
+size, the spare area may have different structures (schemes). All the
+required schemes are defined in ``/drivers/mtd/mtd_nandscheme.c`` (in
+the ``g_nand_sparescheme*`` structures).
+
+Due to the nature of NAND flash, upon testing, a manufaturer may decide that
+a certain block fails some test(s), and mark it as a **bad block** by
+writing a certain value in a certain position in the spare area (depends on
+data area's size, and thus, the spare area's scheme) of every page in it.
+
+.. NOTE::
+ * While certain blocks may *still work* even if they are marked as bad,
+ it's inadvisable to store any data in it.
+
+ * The spare data is the **only** record of a block being bad or not.
+ Please do not erase it.
+
+ * Certain blocks may become bad after continuous usage, and would need
+ to be marked as such by either the filesystem or the driver.
+
+Currently, this simulator supports only 512 B sized pages, which means it
+will follow the ``g_nand_sparescheme512`` scheme for its spare area, and
+thus have a bad block marker at index ``5``.
+
+If a block is *not* bad, it contains a value of ``0xff`` in the place of a
+bad block marker. Any other value denote it's a bad block.
+
+RAM to Device (Lower Half)
+==========================
+
+Since this is an emulation, RAM of the host running the simulator is used
+to create the device. While the speed of operations won't be even close to
+the original, this being in the RAM, which works multitudes faster than
+actual device, the functionality on the other hand has been kept consistent
+to the utmost.
+
+First, ``/include/nuttx/mtd/nand.h`` has a structure ``struct nand_dev_s``
+defining a raw NAND MTD device (lowest level). Its field ``nand_dev_s->raw``
+is of type ``struct nand_raw_s *`` (defined in
+``include/nuttx/mtd/nand_raw.h``), and this is what will hold the methods
+for the raw device. There are primarily 3 methods that need to be looked
+into:
+
+* eraseblock
+* rawread
+* rawwrite
+
+Conforming to the functionality of NAND flashes, these three were implemented
+as ``nand_ram_*`` in ``/drivers/mtd/nand_ram.c`` to emulate RAM into a
+virtual NAND flash.
+
+While in real devices, the spare area follows the data area (in most schemes)
+, since this is virtual, we can get away with keeping the two into two
+separate arrays, namely ``nand_ram_flash_data`` and ``nand_ram_flash_spare``
+for data and spare respectively. Each array has as many elements as number
+of pages in the device.
+
+As the spare areas has some spare bytes we can use, some space is used as
+counters for the reads/writes/erases each page faces, thus giving a clear
+picture of wear of the virtual device to the tester.
+
+.. NOTE::
+ ECC extension has not been implemented yet, so ECC bits in spare are
+ yet to be used or initialized properly.
+
+The method ``nand_ram_initialize()`` takes in a preallocated space for a
+raw device (of type ``struct nand_raw_s`` as defined in
+``include/nuttx/mtd/nand_raw.h``) and attaches these 3 custom methods as well
+as device information like page size, block size, etc. to it. These form
+the lower half of the driver.
+
+Upper Half
+==========
+
+The method ``nand_ram_initialize()`` also initializes a
+``struct mtd_dev_s *`` (defined in ``include/nuttx/mtd/mtd.h``), which it
+returns. This structure contains a reference to our custom lower half in
+``mtd_dev_s->raw``, as well as an upper half containing methods ``nand_*``
+(defined in ``drivers/mtd/mtd_nand.c``).
+
+Wrapper Over Upper Half
+=======================
+
+The upper half, along with the lower half attached to it, received from
+``nand_ram_initialize()`` contains these 5 methods for the upper half:
+
+* erase
+* bread
+* bwrite
+* ioctl
+* isbad
+* markbad
+
+Each driver's upper half needs to be registered with NuttX before it can
+appear in the list of devices (in ``/dev``). Instead of the previously
+acquired upper-half, we'll be registering a wrapper over it, to improve
+logging. The wrapper methods are defined as ``nand_wrapper_*`` in
+``drivers/mtd/mtd_nandwrapper.c``.
+
+Here's a complicated bit. The actual upper half is an MTD device, but
+more specifically, it is a NAND MTD device, which is represented by
+``struct nand_dev_s``. Due to how it is defined, ``struct mtd_dev_s`` forms
+the very start of ``struct nand_dev_s``, and hence they can be type-casted
+to each other (provided required memory is accessible). Our wrapper, being a
+wrapper over an MTD device, is an MTD device itself as well. MTD device
+methods take in a ``struct mtd_dev_s *dev`` which describe the device
+itself (which is the actual device that is registered using
+``register_mtddriver``), which includes its methods. Our wrapper methods
+receive such a device as well, which contains the wrapper device including
+the wrapper functions. But, this way, there is no way of accessing the
+methods of the actual upper half itself. Thus, instead of ``dev`` being
+of type ``struct nand_dev_s``, it is actually of type
+``struct nand_wrapper_dev_s`` which is a superset of ``struct nand_dev_s``,
+who itself is a superset of ``struct mtd_dev_s``. Similar to previous case,
+``struct mtd_dev_s`` forms the very start of ``struct nand_wrapper_dev_s``,
+and thus the types are inter-changeable.
+
+The methods ``nand_wrapper_*`` in ``drivers/mtd/mtd_nandwrapper.c`` all
+pass the parameters to corresponding method of the actual upper half
+after logging it. *But, the device passed on to the actual upper half
+is still the wrapper, not the actual upper half, as the upper half methods
+may call the other methods as well internally and we might want to log
+them as well*.
+
+Registering Device & Daemon
+===========================
+
+This wrapper is then registered using ``register_mtddriver``, and this
+whole thing is converted to be a daemon, so that the device can keep running
+in the background.
+
+Making it a daemon is achieved by using ``fork()``, killing the parent, and
+using ``daemon()`` in child.
+
+Known Issues
+============
+
+* ECC is not implemented yet.
+* MLC NAND Flash is not implemented yet.
+* Due to the fixed name of the device, there can't be more than one instance
+ of this virtual device.
\ No newline at end of file
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 0cf5f9de08f..5d75e849729 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -271,6 +271,71 @@ config MTD_NAND_EMBEDDEDECC
only one supported) is Micron, 4-bit ECC, device size = 1Gb or 2Gb
or 4Gb.
+config MTD_NAND_RAM
+ bool "Enable virtual NAND Flash"
+ default n
+ ---help---
+ Enable a virtual NAND Flash device emulated from RAM in the simulator.
+
+if MTD_NAND_RAM
+
+config MTD_NAND_RAM_SIZE
+ int "Size of the virtual NAND Flash in MB."
+ default 2
+ ---help---
+ Size of the virtual NAND Flash in megabytes.
+
+config MTD_NAND_RAM_DEBUG
+ bool "Enable debugging of virtual NAND Flash."
+ default n
+ ---help---
+ Enables debug info being written to syslog for virtual NAND Flash
+ device emulated from RAM in the simulator.
+
+config MTD_NAND_RAM_DEBUG_LEVEL
+ int "Debugging level of virtual NAND Flash raw lower half operations."
+ depends on MTD_NAND_RAM_DEBUG
+ default 1
+ range 1 3
+ ---help---
+ 1 - Log every instruction.
+ 2 - Log every 5 instructions.
+ 3 - Log every 10 instructions.
+
+config MTD_NAND_RAM_STATUS
+ int "Log status of virtual NAND Flash."
+ depends on MTD_NAND_RAM_DEBUG
+ default 3
+ range 1 8
+ ---help---
+ 1 - Log every instruction.
+ 2 - Log every 5 instructions.
+ 3 - Log every 10 instructions.
+ 4 - Log every 50 instructions.
+ 5 - Log every 100 instructions.
+ 6 - Log every 500 instructions.
+ 7 - Log every 1000 instructions.
+ 8 - Log every 5000 instructions.
+
+endif #MTD_NAND_RAM
+
+config MTD_NAND_WRAPPER
+ bool "Enable logging wrapper for NAND flash upper half operations."
+ default n
+
+if MTD_NAND_WRAPPER
+
+config MTD_NAND_WRAPPER_DEBUG_LEVEL
+ int "Log level of upper half of virtual NAND Flash."
+ default 1
+ range 1 3
+ ---help---
+ 1 - Log every instruction.
+ 2 - Log every 5 instructions.
+ 3 - Log every 10 instructions.
+
+endif # MTD_NAND_WRAPPER
+
endif # MTD_NAND
config RPMSGMTD
diff --git a/drivers/mtd/Make.defs b/drivers/mtd/Make.defs
index 549b6c3fb89..6956610c3cd 100644
--- a/drivers/mtd/Make.defs
+++ b/drivers/mtd/Make.defs
@@ -60,6 +60,15 @@ CSRCS += mtd_nand.c mtd_onfi.c mtd_nandscheme.c mtd_nandmodel.c mtd_modeltab.c
ifeq ($(CONFIG_MTD_NAND_SWECC),y)
CSRCS += mtd_nandecc.c hamming.c
endif
+
+ifeq ($(CONFIG_MTD_NAND_RAM), y)
+CSRCS += mtd_nandram.c
+endif
+
+ifeq ($(CONFIG_MTD_NAND_WRAPPER), y)
+CSRCS += mtd_nandwrapper.c
+endif
+
endif
ifeq ($(CONFIG_RAMMTD),y)
diff --git a/drivers/mtd/mtd_nand.c b/drivers/mtd/mtd_nand.c
index f4776d8a6f2..88175faceef 100644
--- a/drivers/mtd/mtd_nand.c
+++ b/drivers/mtd/mtd_nand.c
@@ -44,6 +44,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/drivers/mtd/mtd_nandram.c b/drivers/mtd/mtd_nandram.c
new file mode 100644
index 00000000000..cfaaef7366e
--- /dev/null
+++ b/drivers/mtd/mtd_nandram.c
@@ -0,0 +1,475 @@
+/****************************************************************************
+ * drivers/mtd/mtd_nandram.c
+ * This file deals with the raw lower half of the device driver, and manages
+ * reading and writing to the actual NAND Flash device that has been emulated
+ * from RAM.
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+#include
+#include
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_NAND_RAM_DEBUG
+
+#define NAND_RAM_DEBUG_1 1
+#define NAND_RAM_DEBUG_2 5
+#define NAND_RAM_DEBUG_3 10
+
+#define NAND_RAM_STATUS_1 1
+#define NAND_RAM_STATUS_2 5
+#define NAND_RAM_STATUS_3 10
+#define NAND_RAM_STATUS_4 50
+#define NAND_RAM_STATUS_5 100
+#define NAND_RAM_STATUS_6 500
+#define NAND_RAM_STATUS_7 1000
+#define NAND_RAM_STATUS_8 5000
+
+#if CONFIG_MTD_NAND_RAM_DEBUG_LEVEL == 1
+#define NAND_RAM_DEBUG_LEVEL NAND_RAM_DEBUG_1
+#elif CONFIG_MTD_NAND_RAM_DEBUG_LEVEL == 2
+#define NAND_RAM_DEBUG_LEVEL NAND_RAM_DEBUG_2
+#elif CONFIG_MTD_NAND_RAM_DEBUG_LEVEL == 3
+#define NAND_RAM_DEBUG_LEVEL NAND_RAM_DEBUG_3
+#endif /* CONFIG_MTD_NAND_RAM_DEBUG_LEVEL */
+
+#if CONFIG_MTD_NAND_RAM_STATUS == 1
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_1
+#elif CONFIG_MTD_NAND_RAM_STATUS == 2
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_2
+#elif CONFIG_MTD_NAND_RAM_STATUS == 3
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_3
+#elif CONFIG_MTD_NAND_RAM_STATUS == 4
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_4
+#elif CONFIG_MTD_NAND_RAM_STATUS == 5
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_5
+#elif CONFIG_MTD_NAND_RAM_STATUS == 6
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_6
+#elif CONFIG_MTD_NAND_RAM_STATUS == 7
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_7
+#elif CONFIG_MTD_NAND_RAM_STATUS == 8
+#define NAND_RAM_STATUS_LEVEL NAND_RAM_STATUS_8
+#endif /* CONFIG_MTD_NAND_RAM_STATUS */
+
+#define NAND_RAM_LOG(str, ...) \
+ { \
+ if (nand_ram_ins_i % NAND_RAM_DEBUG_LEVEL == 0) \
+ { \
+ syslog(LOG_DEBUG, "nand_ram: " str, __VA_ARGS__); \
+ } \
+ } \
+
+#define NAND_RAM_STATUS_LOG(str, ...) \
+ syslog(LOG_DEBUG, "nand_ram_status: " str, __VA_ARGS__);
+
+#else
+
+#define NAND_RAM_LOG
+#define NAND_RAM_STATUS_LOG
+
+#endif /* CONFIG_MTD_NAND_RAM_DEBUG */
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nand_ram_data_s
+{
+ uint8_t page[NAND_RAM_PAGE_SIZE / 8];
+};
+
+/* 512 B page spare scheme */
+
+struct nand_ram_spare_s
+{
+ uint8_t ecc_0; /* 0 */
+ uint8_t ecc_1;
+ uint8_t ecc_2;
+ uint8_t ecc_3;
+ uint8_t __res1;
+ uint8_t bad; /* 5 */ /* NAND_RAM_BLOCK_* */
+ uint8_t ecc_4;
+ uint8_t ecc_5;
+
+ /* Using reserved (8 bytes) */
+
+ uint16_t n_read;
+ uint16_t n_write; /* 10 */
+ uint16_t n_erase;
+ uint8_t free; /* Erased page: NAND_RAM_PAGE_* */
+ uint8_t __res2;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint64_t nand_ram_ins_i = 0; /* Instruction counter */
+static mutex_t nand_ram_dev_mut;
+static struct nand_ram_data_s nand_ram_flash_data[NAND_RAM_N_PAGES];
+static struct nand_ram_spare_s nand_ram_flash_spare[NAND_RAM_N_PAGES];
+
+/* Hard coded array for bad block indexes */
+
+static int g_nand_ram_rand_bad_blk_indx[] =
+ {
+ 4, 14, 19, 21, 28, 30, 107,
+ 108, 164, 173, 179, 229, 268,
+ 362, 377, 382, 396, 410, 412,
+ 419, 428, 456, 500, 0
+ };
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * External Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nand_ram_storage_status
+ *
+ * Description:
+ * Writes per-page status of virtual NAND Flash.
+ *
+ ****************************************************************************/
+
+static void nand_ram_storage_status(void)
+{
+ uint32_t i;
+ uint16_t reads;
+ uint16_t writes;
+ uint16_t erases;
+ uint8_t bad;
+
+ /* Wear */
+
+ for (i = 0; i < NAND_RAM_N_PAGES; i++)
+ {
+ reads = nand_ram_flash_spare[i].n_read;
+ writes = nand_ram_flash_spare[i].n_write;
+ erases = nand_ram_flash_spare[i].n_erase;
+ bad = (nand_ram_flash_spare[i].bad != NAND_RAM_BLOCK_GOOD);
+
+ NAND_RAM_STATUS_LOG(
+ "Block %3d, Page %6d, Bad: %1d |"
+ " Reads: %6d, Writes: %6d, Erases: %6d\n",
+ i >> NAND_RAM_LOG_PAGES_PER_BLOCK, i, bad,
+ reads, writes, erases);
+ }
+
+ return;
+}
+
+static inline void nand_ram_status(void)
+{
+ if (nand_ram_ins_i % NAND_RAM_STATUS_LEVEL == 0)
+ {
+ nand_ram_storage_status();
+ }
+}
+
+/****************************************************************************
+ * Name: nand_ram_storage_init
+ *
+ * Description:
+ * Initializes the actual NAND Device that is emulated from RAM.
+ *
+ ****************************************************************************/
+
+static void nand_ram_storage_init(void)
+{
+ int i;
+
+ memset(nand_ram_flash_data, 0xff,
+ sizeof(struct nand_ram_data_s) * NAND_RAM_N_PAGES);
+ memset(nand_ram_flash_spare, 0,
+ sizeof(struct nand_ram_spare_s) * NAND_RAM_N_PAGES);
+
+ for (i = 0; i < NAND_RAM_N_PAGES; i++)
+ {
+ nand_ram_flash_spare[i].free = NAND_RAM_PAGE_FREE;
+ nand_ram_flash_spare[i].bad = NAND_RAM_BLOCK_GOOD;
+ }
+
+ /* Bad blocks */
+
+ for (i = 0;
+ g_nand_ram_rand_bad_blk_indx[i] != 0 &&
+ g_nand_ram_rand_bad_blk_indx[i] < NAND_RAM_N_BLOCKS;
+ i++)
+ {
+ int j;
+
+ for (j = 0; j < NAND_RAM_PAGES_PER_BLOCK; j++)
+ {
+ int page = (g_nand_ram_rand_bad_blk_indx[i] <<
+ NAND_RAM_LOG_PAGES_PER_BLOCK)+j;
+
+ /* Set bad block marker to Anything but NAND_RAM_BLOCK_GOOD */
+
+ nand_ram_flash_spare[page].bad = 0;
+ }
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nand_ram_eraseblock
+ *
+ * Description:
+ * Erases a block on the device.
+ *
+ * Input Parameters:
+ * raw: NAND MTD Device raw structure.
+ * block: Block number (0 indexing) to erase
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ ****************************************************************************/
+
+int nand_ram_eraseblock(FAR struct nand_raw_s *raw, off_t block)
+{
+ int i;
+ uint32_t start_page;
+ uint32_t end_page;
+
+ start_page = block << NAND_RAM_LOG_PAGES_PER_BLOCK;
+ end_page = start_page + NAND_RAM_PAGES_PER_BLOCK;
+
+ nxmutex_lock(&nand_ram_dev_mut);
+ nand_ram_ins_i++;
+
+ NAND_RAM_LOG(
+ "[LOWER %lu | %s] Block %d, Start Page: %d, Last Page: %d",
+ nand_ram_ins_i, "eraseblock", block, start_page, end_page - 1
+ );
+ nand_ram_status();
+
+ /* [start_page, end_page) is cleared (all bits are set) */
+
+ memset(nand_ram_flash_data + start_page, 0xff,
+ (end_page - start_page) * sizeof(struct nand_ram_data_s));
+ for (i = start_page; i < end_page; i++)
+ {
+ nand_ram_flash_spare[i].n_erase++;
+ nand_ram_flash_spare[i].free = 1;
+ }
+
+ NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "eraseblock");
+
+ nxmutex_unlock(&nand_ram_dev_mut);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nand_ram_rawread
+ *
+ * Description:
+ * Reads a page from the device.
+ *
+ * Input Parameters:
+ * raw: NAND MTD Device raw structure.
+ * block: Block number (0 indexing) to erase
+ * page: Page number (0 indexing) in (relative to) that block
+ * data: Preallocated memory where the data will be copied to
+ * spare: Preallocated memory where the spare data will be copied to
+ *
+ * Returned Value:
+ * 0: Successful
+ *
+ ****************************************************************************/
+
+int nand_ram_rawread(FAR struct nand_raw_s *raw, off_t block,
+ unsigned int page, FAR void *data, FAR void *spare)
+{
+ int ret;
+ uint32_t read_page;
+ struct nand_ram_data_s *read_page_data;
+ struct nand_ram_spare_s *read_page_spare;
+
+ read_page = (block << NAND_RAM_LOG_PAGES_PER_BLOCK) + page;
+ read_page_data = nand_ram_flash_data + read_page;
+ read_page_spare = nand_ram_flash_spare + read_page;
+
+ ret = OK;
+
+ nxmutex_lock(&nand_ram_dev_mut);
+ nand_ram_ins_i++;
+
+ NAND_RAM_LOG("[LOWER %lu | %s] Page %d\n",
+ nand_ram_ins_i, "rawread", read_page);
+ nand_ram_status();
+
+ if (nand_ram_flash_spare[read_page].bad != NAND_RAM_BLOCK_GOOD)
+ {
+ ret = -EFAULT;
+ NAND_RAM_LOG("[LOWER %lu | %s] Failed: %s\n",
+ nand_ram_ins_i, "rawread", EFAULT_STR);
+ goto errout;
+ }
+
+ nand_ram_flash_spare[read_page].n_read++;
+
+ if (data != NULL)
+ {
+ memcpy(data, (const void *)read_page_data, NAND_RAM_PAGE_SIZE);
+ }
+
+ if (spare != NULL)
+ {
+ memcpy(spare, (const void *)read_page_spare, NAND_RAM_PAGE_SIZE);
+ }
+
+ NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "rawread");
+
+errout:
+ nxmutex_unlock(&nand_ram_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_ram_rawread
+ *
+ * Description:
+ * Writes a page to the device.
+ *
+ * Input Parameters:
+ * raw: NAND MTD Device raw structure.
+ * block: Block number (0 indexing) to erase
+ * page: Page number (0 indexing) in (relative to) that block
+ * data: Preallocated memory where the data will be copied to
+ * spare: Preallocated memory where the spare data will be copied to
+ *
+ * Returned Value:
+ * 0: Successful
+ * -EACCESS: The page's block needs to be erased first before writing to it
+ *
+ ****************************************************************************/
+
+int nand_ram_rawwrite(FAR struct nand_raw_s *raw, off_t block,
+ unsigned int page, FAR const void *data,
+ FAR const void *spare)
+{
+ int ret;
+ uint32_t write_page;
+ struct nand_ram_data_s *write_page_data;
+ struct nand_ram_spare_s *write_page_spare;
+
+ write_page = (block << NAND_RAM_LOG_PAGES_PER_BLOCK) + page;
+ write_page_data = nand_ram_flash_data + write_page;
+ write_page_spare = nand_ram_flash_spare + write_page;
+
+ ret = OK;
+
+ nxmutex_lock(&nand_ram_dev_mut);
+ nand_ram_ins_i++;
+
+ NAND_RAM_LOG("[LOWER %lu | %s] Page %d\n",
+ nand_ram_ins_i, "rawwrite", write_page);
+ nand_ram_status();
+
+ if (nand_ram_flash_spare[write_page].free != NAND_RAM_PAGE_FREE)
+ {
+ ret = -EACCES;
+ NAND_RAM_LOG("[LOWER %lu | %s] Failed: %s\n",
+ nand_ram_ins_i, "rawwrite", EACCES_STR);
+ goto errout;
+ }
+
+ nand_ram_flash_spare[write_page].n_write++;
+
+ if (data != NULL)
+ {
+ memcpy((void *)write_page_data, data, NAND_RAM_PAGE_SIZE);
+ }
+
+ if (spare != NULL)
+ {
+ memcpy((void *)write_page_spare, data, NAND_RAM_PAGE_SIZE);
+ }
+
+ NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "rawwrite");
+
+errout:
+ nxmutex_unlock(&nand_ram_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_ram_init
+ *
+ * Description:
+ * Driver init.
+ *
+ * Input Parameters:
+ * raw: NAND MTD Device raw structure.
+ *
+ * Returned Value:
+ * A non-NULL MTD driver instance is returned on success. NULL is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *nand_ram_initialize(struct nand_raw_s *raw)
+{
+ NAND_RAM_LOG("[LOWER | %s]\n", "initialize");
+
+ nand_ram_storage_init();
+ nxmutex_init(&nand_ram_dev_mut);
+
+ raw->model.devid = 123;
+ raw->model.pagesize = NAND_RAM_PAGE_SIZE;
+ raw->model.sparesize = NAND_RAM_SPARE_SIZE;
+ raw->model.devsize = NAND_RAM_SIZE / (1024 * 1024);
+ raw->model.blocksize = NAND_RAM_BLOCK_SIZE / 1024;
+ raw->model.scheme = &g_nand_sparescheme512;
+
+ raw->eraseblock = nand_ram_eraseblock;
+ raw->rawread = nand_ram_rawread;
+ raw->rawwrite = nand_ram_rawwrite;
+
+ return nand_raw_initialize(raw);
+}
diff --git a/drivers/mtd/mtd_nandwrapper.c b/drivers/mtd/mtd_nandwrapper.c
new file mode 100644
index 00000000000..83e6bbc9862
--- /dev/null
+++ b/drivers/mtd/mtd_nandwrapper.c
@@ -0,0 +1,418 @@
+/****************************************************************************
+ * drivers/mtd/mtd_nandwrapper.c
+ * This deals with the wrapper over the upper half of the driver, to enable
+ * logging for debugging, and essentially passes the parameters right to the
+ * actual upper half of the NAND Flash device driver without changing them.
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define NAND_WRAPPER_DEBUG_1 1
+#define NAND_WRAPPER_DEBUG_2 5
+#define NAND_WRAPPER_DEBUG_3 10
+
+#if CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL == 1
+#define NAND_WRAPPER_DEBUG_LEVEL NAND_WRAPPER_DEBUG_1
+#elif CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL == 2
+#define NAND_WRAPPER_DEBUG_LEVEL NAND_WRAPPER_DEBUG_2
+#elif CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL == 3
+#define NAND_WRAPPER_DEBUG_LEVEL NAND_WRAPPER_DEBUG_3
+#endif /* CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL */
+
+#define NAND_WRAPPER_LOG(str, ...) \
+ { \
+ if(nand_wrapper_ins_i % NAND_WRAPPER_DEBUG_LEVEL == 0) \
+ { \
+ syslog(LOG_DEBUG, "nand_wrapper: " str, __VA_ARGS__); \
+ } \
+ }
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint64_t nand_wrapper_ins_i = 0; /* Instruction counter */
+static mutex_t nand_wrapper_dev_mut;
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * External Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nand_wrapper_erase
+ *
+ * Description:
+ * Wrapper for NAND MTD erase method.
+ *
+ * Input Parameters:
+ * dev: NAND MTD Device (with an actual type of `nand_wrapper_dev_s`
+ * startblock: Block number (0-indexing) to start erasing
+ * nblocks: Number of blocks to erase
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ * Assumptions/Limitations:
+ * This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
+ *
+ ****************************************************************************/
+
+int nand_wrapper_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+ size_t nblocks)
+{
+ int ret;
+ FAR struct nand_wrapper_dev_s *nand_dev;
+
+ nand_dev = (struct nand_wrapper_dev_s *)dev;
+
+ nxmutex_lock(&nand_wrapper_dev_mut);
+ nand_wrapper_ins_i++;
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Startblock: %d, N Blocks: %ld\n",
+ nand_wrapper_ins_i, "erase", startblock, nblocks);
+ DEBUGASSERT(nand_dev && nand_dev->under.mtd.erase);
+
+ ret = nand_dev->under.mtd.erase(dev, startblock, nblocks);
+
+ if (ret >= 0)
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
+ nand_wrapper_ins_i, "erase");
+ }
+ else
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
+ nand_wrapper_ins_i, "erase", ret);
+ }
+
+ nxmutex_unlock(&nand_wrapper_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_wrapper_bread
+ *
+ * Description:
+ * Wrapper for NAND MTD bread method.
+ *
+ * Input Parameters:
+ * dev: MTD Device
+ * startpage: Page number (0-indexing) to start reading
+ * npages: Number of pages to read.
+ * buffer: Preallocated memory where the data will be copied to
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ * Assumptions/Limitations:
+ * This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
+ *
+ ****************************************************************************/
+
+ssize_t nand_wrapper_bread(FAR struct mtd_dev_s *dev, off_t startpage,
+ size_t npages, FAR uint8_t *buffer)
+{
+ int ret;
+ FAR struct nand_wrapper_dev_s *nand_dev;
+
+ nand_dev = (struct nand_wrapper_dev_s *)dev;
+
+ nxmutex_lock(&nand_wrapper_dev_mut);
+ nand_wrapper_ins_i++;
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] "
+ "Startblock: %d, N Pages: %ld, Buffer: %p\n",
+ nand_wrapper_ins_i, "bread", startpage, npages, buffer);
+ DEBUGASSERT(nand_dev && nand_dev->under.mtd.bread);
+
+ ret = nand_dev->under.mtd.bread(dev, startpage, npages, buffer);
+
+ if (ret >= 0)
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
+ nand_wrapper_ins_i, "bread");
+ }
+ else
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
+ nand_wrapper_ins_i, "bread", ret);
+ }
+
+ nxmutex_unlock(&nand_wrapper_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_wrapper_bwrite
+ *
+ * Description:
+ * Wrapper for NAND MTD bwrite method.
+ *
+ * Input Parameters:
+ * dev: MTD Device
+ * startpage: Page number (0-indexing) to start reading
+ * npages: Number of pages to read.
+ * buffer: Data which will be written to the device
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ * Assumptions/Limitations:
+ * This assumes the length of `buffer` would be the same as the size of
+ * `npages * block_size`. This also assumes `dev` is specifically of
+ * type `struct nand_wrapper_dev_s *`
+ *
+ ****************************************************************************/
+
+ssize_t nand_wrapper_bwrite(FAR struct mtd_dev_s *dev, off_t startpage,
+ size_t npages, FAR const uint8_t *buffer)
+{
+ int ret;
+ FAR struct nand_wrapper_dev_s *nand_dev;
+
+ nand_dev = (struct nand_wrapper_dev_s *)dev;
+
+ nxmutex_lock(&nand_wrapper_dev_mut);
+ nand_wrapper_ins_i++;
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] "
+ "Startblock: %d, N Pages: %ld, Buffer: %p \n",
+ nand_wrapper_ins_i, "bwrite", startpage, npages, buffer);
+ DEBUGASSERT(nand_dev && nand_dev->under.mtd.bwrite);
+
+ ret = nand_dev->under.mtd.bwrite(dev, startpage, npages, buffer);
+
+ if (ret >= 0)
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
+ nand_wrapper_ins_i, "bwrite");
+ }
+ else
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
+ nand_wrapper_ins_i, "bwrite", ret);
+ }
+
+ nxmutex_unlock(&nand_wrapper_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_wrapper_ioctl
+ *
+ * Description:
+ * Wrapper for NAND MTD ioctl method.
+ *
+ * Input Parameters:
+ * dev: MTD Device
+ * cmd: Command for IOCTL
+ * arg: Any argument required by command
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ * Assumptions/Limitations:
+ * This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
+ *
+ ****************************************************************************/
+
+int nand_wrapper_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+ unsigned long arg)
+{
+ int ret;
+ FAR struct nand_wrapper_dev_s *nand_dev;
+
+ nand_dev = (struct nand_wrapper_dev_s *)dev;
+
+ nxmutex_lock(&nand_wrapper_dev_mut);
+ nand_wrapper_ins_i++;
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Command: %d, Arg : %ld\n",
+ nand_wrapper_ins_i, "ioctl", cmd, arg);
+ DEBUGASSERT(nand_dev && nand_dev->under.mtd.ioctl);
+
+ ret = nand_dev->under.mtd.ioctl(dev, cmd, arg);
+
+ if (ret >= 0)
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
+ nand_wrapper_ins_i, "ioctl");
+ }
+ else
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
+ nand_wrapper_ins_i, "ioctl", ret);
+ }
+
+ nxmutex_unlock(&nand_wrapper_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_wrapper_isbad
+ *
+ * Description:
+ * Wrapper for NAND MTD isbad method.
+ *
+ * Input Parameters:
+ * dev: MTD Device
+ * block: Block number (0-indexing) to check if it is bad
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ * Assumptions/Limitations:
+ * This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
+ *
+ ****************************************************************************/
+
+int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block)
+{
+ int ret;
+ FAR struct nand_wrapper_dev_s *nand_dev;
+
+ nand_dev = (struct nand_wrapper_dev_s *)dev;
+
+ nxmutex_lock(&nand_wrapper_dev_mut);
+ nand_wrapper_ins_i++;
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Blocks: %d\n",
+ nand_wrapper_ins_i, "isbad", block);
+ DEBUGASSERT(nand_dev && nand_dev->under.mtd.isbad);
+
+ ret = nand_dev->under.mtd.isbad(dev, block);
+
+ if (ret >= 0)
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
+ nand_wrapper_ins_i, "isbad");
+ }
+ else
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
+ nand_wrapper_ins_i, "isbad", ret);
+ }
+
+ nxmutex_unlock(&nand_wrapper_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_wrapper_markbad
+ *
+ * Description:
+ * Wrapper for NAND MTD markbad method.
+ *
+ * Input Parameters:
+ * dev: MTD Device
+ * block: Block number (0-indexing) to mark it as bad
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ * Assumptions/Limitations:
+ * This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
+ *
+ ****************************************************************************/
+
+int nand_wrapper_markbad(FAR struct mtd_dev_s *dev, off_t block)
+{
+ int ret;
+ FAR struct nand_wrapper_dev_s *nand_dev;
+
+ nand_dev = (struct nand_wrapper_dev_s *)dev;
+
+ nxmutex_lock(&nand_wrapper_dev_mut);
+ nand_wrapper_ins_i++;
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Blocks: %d\n",
+ nand_wrapper_ins_i, "markbad", block);
+ DEBUGASSERT(nand_dev && nand_dev->under.mtd.markbad);
+
+ ret = nand_dev->under.mtd.markbad(dev, block);
+
+ if (ret >= 0)
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
+ nand_wrapper_ins_i, "markbad");
+ }
+ else
+ {
+ NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
+ nand_wrapper_ins_i, "markbad", ret);
+ }
+
+ nxmutex_unlock(&nand_wrapper_dev_mut);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nand_wrapper_initialize
+ *
+ * Description:
+ * Initializes wrapper.
+ *
+ * Returned Value:
+ * 0: Successful
+ * < 0: Error
+ *
+ ****************************************************************************/
+
+void nand_wrapper_initialize(void)
+{
+ nxmutex_init(&nand_wrapper_dev_mut);
+}
diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h
index 8a6b5ec615b..91cc8ee6def 100644
--- a/include/nuttx/compiler.h
+++ b/include/nuttx/compiler.h
@@ -207,8 +207,8 @@
/* Branch prediction */
-# define predict_true(x) __builtin_expect(!!(x), 1)
-# define predict_false(x) __builtin_expect((x), 0)
+# define predict_true(x) __builtin_expect(!!(x), 1)
+# define predict_false(x) __builtin_expect(!!(x), 0)
/* Code locate */
diff --git a/include/nuttx/mtd/nand.h b/include/nuttx/mtd/nand.h
index 08ad677dc9e..4be864ee1e1 100644
--- a/include/nuttx/mtd/nand.h
+++ b/include/nuttx/mtd/nand.h
@@ -98,7 +98,7 @@ extern "C"
*
* Returned Value:
* A non-NULL MTD driver instance is returned on success. NULL is
- * returned on any failaure.
+ * returned on any failure.
*
****************************************************************************/
diff --git a/include/nuttx/mtd/nand_ram.h b/include/nuttx/mtd/nand_ram.h
new file mode 100644
index 00000000000..5229882e42b
--- /dev/null
+++ b/include/nuttx/mtd/nand_ram.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * include/nuttx/mtd/nand_ram.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+#ifndef __INCLUDE_NUTTX_MTD_NAND_RAM_H
+#define __INCLUDE_NUTTX_MTD_NAND_RAM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define NAND_RAM_DEBUG CONFIG_MTD_NAND_RAM_DEBUG
+
+#define NAND_RAM_B(x) (x)
+#define NAND_RAM_KB(x) (NAND_RAM_B(x) << 10)
+#define NAND_RAM_MB(x) (NAND_RAM_KB(x) << 10)
+
+#define NAND_RAM_SIZE NAND_RAM_MB(CONFIG_MTD_NAND_RAM_SIZE)
+
+#define NAND_RAM_LOG_PAGES_PER_BLOCK ((uint32_t) 7)
+#define NAND_RAM_PAGE_SIZE ((uint32_t) (1 << 9)) /* 512 B */
+#define NAND_RAM_SPARE_SIZE ((uint32_t) (1 << 4)) /* 16 B */
+#define NAND_RAM_N_PAGES ((uint32_t) NAND_RAM_SIZE / NAND_RAM_PAGE_SIZE)
+#define NAND_RAM_TOTAL_PAGE_SIZE ((uint32_t) (NAND_RAM_PAGE_SIZE + NAND_RAM_SPARE_SIZE))
+#define NAND_RAM_PAGES_PER_BLOCK ((uint32_t) (NAND_RAM_BLOCK_SIZE / NAND_RAM_PAGE_SIZE))
+#define NAND_RAM_N_BLOCKS ((uint32_t) (NAND_RAM_N_PAGES / NAND_RAM_PAGES_PER_BLOCK))
+#define NAND_RAM_BLOCK_SIZE ((uint32_t) ((1 << NAND_RAM_LOG_PAGES_PER_BLOCK) * NAND_RAM_PAGE_SIZE))
+
+#define NAND_RAM_PAGE_WRITTEN 0
+#define NAND_RAM_PAGE_FREE 1
+
+#define NAND_RAM_BLOCK_GOOD 0xff
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+EXTERN FAR struct mtd_dev_s *g_nand_ram_mtd_wrapper;
+EXTERN FAR struct mtd_dev_s *g_nand_ram_mtd_under;
+EXTERN FAR struct nand_raw_s *g_nand_mtd_raw;
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int nand_ram_eraseblock(FAR struct nand_raw_s *raw, off_t block);
+int nand_ram_rawread(FAR struct nand_raw_s *raw, off_t block,
+ unsigned int page, FAR void *data, FAR void *spare);
+int nand_ram_rawwrite(FAR struct nand_raw_s *raw, off_t block,
+ unsigned int page, FAR const void *data,
+ FAR const void *spare);
+FAR struct mtd_dev_s *nand_ram_initialize(struct nand_raw_s *raw);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TESTING_NAND_RAM_NAND_RAM_H */
\ No newline at end of file
diff --git a/include/nuttx/mtd/nand_wrapper.h b/include/nuttx/mtd/nand_wrapper.h
new file mode 100644
index 00000000000..28304d107be
--- /dev/null
+++ b/include/nuttx/mtd/nand_wrapper.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+ * include/nuttx/mtd/nand_wrapper.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+#ifndef __INCLUDE_NUTTX_MTD_NAND_WRAPPER_H
+#define __INCLUDE_NUTTX_MTD_NAND_WRAPPER_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+#include
+
+#include
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct nand_wrapper_dev_s
+{
+ struct nand_dev_s wrapper; /* Wrapper device */
+ struct nand_dev_s under; /* Underlying actuall upper half device */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int nand_wrapper_erase(FAR struct mtd_dev_s *dev, off_t startblock,
+ size_t nblocks);
+ssize_t nand_wrapper_bread(FAR struct mtd_dev_s *dev, off_t startpage,
+ size_t npages, FAR uint8_t *buffer);
+ssize_t nand_wrapper_bwrite(FAR struct mtd_dev_s *dev, off_t startpage,
+ size_t npages, FAR const uint8_t *buffer);
+int nand_wrapper_ioctl(FAR struct mtd_dev_s *dev, int cmd,
+ unsigned long arg);
+int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block);
+int nand_wrapper_markbad(FAR struct mtd_dev_s *dev, off_t block);
+void nand_wrapper_initialize(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TESTING_NAND_RAM_NAND_RAM_H */
\ No newline at end of file