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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************************************************************** | |
* 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"); | |
return –1; | |
} | |
/* Check if partition size is multiple of erase block */ | |
if ( (partszbytes % erasesize) !=0 ) | |
{ | |
w25info("ERROR: Partition size is not multiple of erasesize!\n"); | |
return –1; | |
} | |
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); | |
return –1; | |
} | |
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; | |
} |
Congratulations – that was probably quite an effort. Nuttx will now rock even more!
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.