Using SmartFS on NuttX

After fixing many issues and thanks to help of Greg Nutt and Ken Petit (SmartFS author) finally I got SmartFS working on NuttX.

This is the NuttX initialization with FileSystem debug enabled:

ABCDF
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        5120
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        5120
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        2048
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        2048
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        1016
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        1016
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1

NuttShell (NSH)
nsh>

Now let see the enabled commands:

nsh> ?
help usage:  help [-v] []

[           dd          hexdump     mkdir       ping        test
?           df          ifconfig    mkfifo      ps          true
break       echo        ifdown      mkrd        pwd         uname
cat         exec        ifup        mksmartfs   rm          umount
cd          exit        kill        mh          rmdir       unset
cp          false       losetup     mount       set         usleep
cmp         free        ls          mv          sh          xd
date        help        mb          mw          sleep

Builtin Apps:
flash_eraseall
pppd
tracker
nsh>

And the created devices:

nsh> ls /dev
/dev:
config
console
null
smart0p1
smart0p2
smart0p3
smart0p4
smart0p5
smart0p6
ttyS0
ttyS1
ttyS2
ttyS3
ttyS4
ttyS5
tun
nsh>

Time to format the smartfs partitions:

nsh> flash_eraseall /dev/smart0p1

Create the file system on it:

nsh> mksmartfs /dev/smart0p1
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        5120
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1

nsh> mksmartfs /dev/smart0p2
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        5120
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1

nsh> mksmartfs /dev/smart0p3
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        2048
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1

nsh> mksmartfs /dev/smart0p4
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        2048
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1

nsh> mksmartfs /dev/smart0p5
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        1016
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1

nsh> mksmartfs /dev/smart0p6
smart_scan: SMART Scan
smart_scan:    Erase size:          512
smart_scan:    Erase count:        1016
smart_scan:    Sect/block:            1
smart_scan:    MTD Blk/Sect:          1
nsh>

Finally let to mount it:

nsh> mount -t smartfs /dev/smart0p1 /mnt/
smartfs_mount: SMARTFS:
smartfs_mount:      Sector size:     512
smartfs_mount:      Bytes/sector     507
smartfs_mount:      Num sectors:     5120
smartfs_mount:      Free sectors:    5113
smartfs_mount:      Max filename:    16
smartfs_mount:      RootDirSector:   3
nsh>

Your redemption is drawing near:

nsh> mkdir /mnt/teste

nsh> ls /mnt/
/mnt/:
 teste/

nsh> cd /mnt
nsh> ls -l
/mnt:
 drwxrwxrwx       0 teste/

nsh> df
  Block  Number
  Size   Blocks     Used Available Mounted on
   512     5120        8      5112 /mnt
nsh> 

Does anyone doubt that NuttX rocks?!?

Just for your information this is my configuration:

CONFIG_MTD=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_SECT512=y
CONFIG_MTD_SECT512_ERASED_STATE=0xff
CONFIG_MTD_PARTITION_NAMES=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_CONFIG=y
CONFIG_MTD_CONFIG_RAM_CONSOLIDATE=y
CONFIG_MTD_CONFIG_ERASEDVALUE=0xff
# MTD Device Drivers
# CONFIG_MTD_NAND is not set

CONFIG_RAMMTD=y
CONFIG_RAMMTD_BLOCKSIZE=512
CONFIG_RAMMTD_ERASESIZE=4096
CONFIG_RAMMTD_ERASESTATE=0xff

CONFIG_MTD_SMART=y
CONFIG_MTD_SMART_SECTOR_SIZE=512
# CONFIG_MTD_SMART_WEAR_LEVEL is not set
# CONFIG_MTD_SMART_CONVERT_WEAR_FORMAT is not set
# CONFIG_MTD_SMART_ENABLE_CRC is not set
# CONFIG_MTD_SMART_MINIMIZE_RAM is not set
# CONFIG_MTD_SMART_SECTOR_ERASE_DEBUG is not set
# CONFIG_MTD_SMART_ALLOC_DEBUG is not set

CONFIG_MTD_W25=y


CONFIG_FS_SMARTFS=y
CONFIG_SMARTFS_ERASEDSTATE=0xff
CONFIG_SMARTFS_MAXNAMLEN=16
# CONFIG_SMARTFS_MULTI_ROOT_DIRS is not set
# CONFIG_SMARTFS_ALIGNED_ACCESS is not set

And this gist with the SmartFS partition initialization:

/****************************************************************************
* config/shenzhou/src/stm32_w25.c
*
* Copyright (C) 2012 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/mount.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#ifdef CONFIG_STM32_SPI1
# include <nuttx/spi/spi.h>
# include <nuttx/mtd/mtd.h>
# include <nuttx/fs/smart.h>
# include <nuttx/configdata.h>
#endif
#include "stm32_spi.h"
#include "htptracker.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_DEBUG)
#define w25info dbg
#else
#if defined(CONFIG_DEBUG_INFO)
#define w25info _info
#else
#define w25info(x…)
#endif
#endif
/* Debug ***************************************************************************/
/* Non-standard debug that may be enabled just for testing the watchdog timer */
#define W25_SPI_PORT 1
/* Configuration ************************************************************/
/* Can't support the W25 device if it SPI1 or W25 support is not enabled */
#define HAVE_W25 1
#if !defined(CONFIG_STM32_SPI1) || !defined(CONFIG_MTD_W25)
# undef HAVE_W25
#endif
/* Can't support W25 features if mountpoints are disabled */
#if defined(CONFIG_DISABLE_MOUNTPOINT)
# undef HAVE_W25
#endif
/* Can't support both FAT and SMARTFS */
#if defined(CONFIG_FS_FAT) && defined(CONFIG_FS_SMARTFS)
# warning "Can't support both FAT and SMARTFS — using FAT"
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_w25initialize
*
* Description:
* Initialize and register the W25 FLASH file system.
*
****************************************************************************/
int stm32_w25initialize(int minor)
{
int ret;
#ifdef HAVE_W25
FAR struct spi_dev_s *spi;
FAR struct mtd_dev_s *mtd;
FAR struct mtd_geometry_s geo;
#if defined(CONFIG_MTD_PARTITION_NAMES)
FAR const char *partname = CONFIG_HTPTRACKER_FLASH_PART_NAMES;
#endif
/* Get the SPI port */
spi = stm32_spibus_initialize(W25_SPI_PORT);
if (!spi)
{
w25info("ERROR: Failed to initialize SPI port %d\n", W25_SPI_PORT);
return -ENODEV;
}
/* Now bind the SPI interface to the W25 SPI FLASH driver */
mtd = w25_initialize(spi);
if (!mtd)
{
w25info("ERROR: Failed to bind SPI port %d to the SST 25 FLASH driver\n", W25_SPI_PORT);
return -ENODEV;
}
#ifndef CONFIG_FS_SMARTFS
/* And finally, use the FTL layer to wrap the MTD driver as a block driver */
ret = ftl_initialize(minor, mtd);
if (ret < 0)
{
w25info("ERROR: Initialize the FTL layer\n");
return ret;
}
#else
/* Initialize to provide SMARTFS on the MTD interface */
/* Get the geometry of the FLASH device */
ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
if (ret < 0)
{
w25info("ERROR: mtd->ioctl failed: %d\n", ret);
return ret;
}
#ifdef CONFIG_HTPTRACKER_FLASH_PART
{
int partno;
int partsize;
int partoffset;
int partszbytes;
int erasesize;
const char *partstring = CONFIG_HTPTRACKER_FLASH_PART_LIST;
const char *ptr;
FAR struct mtd_dev_s *mtd_part;
char partref[4];
/* Now create a partition on the FLASH device */
partno = 0;
ptr = partstring;
partoffset = 0;
/* Get the Flash erase size */
erasesize = geo.erasesize;
while (*ptr != '\0')
{
/* Get the partition size */
partsize = atoi(ptr);
partszbytes = (partsize << 10); /* partsize is defined in KB */
/* Check if partition size is bigger then erase block */
if (partszbytes < erasesize)
{
w25info("ERROR: Partition size is lesser than erasesize!\n");
return1;
}
/* Check if partition size is multiple of erase block */
if ( (partszbytes % erasesize) !=0 )
{
w25info("ERROR: Partition size is not multiple of erasesize!\n");
return1;
}
mtd_part = mtd_partition(mtd, partoffset, partszbytes/ erasesize);
partoffset += partszbytes / erasesize;
#ifdef CONFIG_HTPTRACKER_FLASH_CONFIG_PART
/* Test if this is the config partition */
if (CONFIG_HTPTRACKER_FLASH_CONFIG_PART_NUMBER == partno)
{
/* Register the partition as the config device */
mtdconfig_register(mtd_part);
}
else
#endif
{
/* Now initialize a SMART Flash block device and bind it
* to the MTD device.
*/
#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
sprintf(partref, "p%d", partno);
smart_initialize(CONFIG_HTPTRACKER_FLASH_MINOR, mtd_part, partref);
#endif
}
/* Set the partition name */
#if defined(CONFIG_MTD_PARTITION_NAMES)
if (!mtd_part)
{
w25info("Error: failed to create partition %s\n", partname);
return1;
}
mtd_setpartitionname(mtd_part, partname);
/* Now skip to next name. We don't need to split the string here
* because the MTD partition logic will only display names up to
* the comma, thus allowing us to use a single static name
* in the code.
*/
while (*partname != ',' && *partname != '\0')
{
/* Skip to next ',' */
partname++;
}
if (*partname == ',')
{
partname++;
}
#endif
/* Update the pointer to point to the next size in the list */
while ((*ptr >= '0') && (*ptr <= '9'))
{
ptr++;
}
if (*ptr == ',')
{
ptr++;
}
/* Increment the part number */
partno++;
}
}
#else /* CONFIG_HTPTRACKER_FLASH_PART */
/* Configure the device with no partition support */
smart_initialize(CONFIG_HTPTRACKER_FLASH_MINOR, mtd, NULL);
#endif /* CONFIG_HTPTRACKER_FLASH_PART */
#endif /* CONFIG_FS_SMARTFS */
#endif /* HAVE_W25 */
/* Create a RAM MTD device if configured */
#if defined(CONFIG_RAMMTD) && defined(CONFIG_HTPTRACKER_RAMMTD)
{
uint8_t *start = (uint8_t *) kmm_malloc(CONFIG_HTPTRACKER_RAMMTD_SIZE * 1024);
mtd = rammtd_initialize(start, CONFIG_HTPTRACKER_RAMMTD_SIZE * 1024);
mtd->ioctl(mtd, MTDIOC_BULKERASE, 0);
/* Now initialize a SMART Flash block device and bind it to the MTD device */
#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS)
smart_initialize(CONFIG_HTPTRACKER_RAMMTD_MINOR, mtd, NULL);
#endif
}
#endif /* CONFIG_RAMMTD && CONFIG_HTPTRACKER_RAMMTD */
return OK;
}

view raw
stm32_w25.c
hosted with ❤ by GitHub

2 thoughts on “Using SmartFS on NuttX

  1. Hi Celem!
    Yes, SmartFS is a great contribution for NuttX, I think Ken did a great and huge work! I think it is proportional to JFFS2 for Linux (obviously comparing the scale of each system). My work was just to get it working on my board, everything were already in place and my help was just to rise some issues introduced recently that rendered it not working.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s