littlefs与sfud串行flash通用驱动建立FreeRTOS文件系统

littlefs文件系统体积很小,很适合经常断电重启的嵌入式场合,使用过程没发现过文件损坏或数据丢失的问题。
主要由fs_spi.c文件与mid_fs.c文件连接两部分的代码,fs_spi.c初始化SPI Flash文件的硬件接口,按需要修改就行

/** 
* @file         midfs.c 
* @brief        provide file operations API for user,bridging the sfud and littleFS. 
* @details  	formate and mount the spi flash file system. 
* @author       ken deng 
* @date     	2019-01-07 
* @version  	A001 
* @par Copyright (c):  
*        佛山畅联智能科技有限公司
* @par History:          
*   version: ken deng, 2019-01-07, create\n 
*/  

#include "string.h"
#include "mid_fs.h"
#include "system.h"
#include "sfud.h"
#include "fs_spi.h"

//#undef MID_FS_DEBUG

#ifdef MID_FS_DEBUG
    #define	midfs_log(...) do{if(DEBUG(DEBUG_ENABLE)){DBG_LOG("[MIDFS](%ld) ",__LINE__);DBG_LOG(__VA_ARGS__);}}while(0)
    #define midfs_usr(...) do{if(DEBUG(DEBUG_ENABLE)){DBG_LOG("[MIDFS] ");DBG_USR(__VA_ARGS__);}}while(0)
    #define midfs_err(...) do{if(DEBUG(DEBUG_ENABLE)){DBG_LOG("[MIDFS] ");DBG_ERR(__VA_ARGS__);}}while(0)
    #define midfs_dump(...) if(DEBUG(DEBUG_ENABLE)){DBG_DUMP(__VA_ARGS__);}
#else
    #define midfs_log(...)
    #define midfs_usr(...)
    #define midfs_err(...)
    #define midfs_dump(...)
#endif


static SemaphoreHandle_t    midfs_mutex;
static FS_TYPE_STRUCT 		mid_fs;
const sfud_flash *flash;	

/** 
* midfs lock mutex.
* none. 
* @param[in]   none.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
void midfs_lock( void )
{
    xSemaphoreTake( midfs_mutex, portMAX_DELAY );
}

/** 
* midfs unlock mutex.
* none. 
* @param[in]   none.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
void midfs_unlock( void )
{
    xSemaphoreGive( midfs_mutex );
}

/** 
* midfs mutex init.
* none. 
* @param[in]   none.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
void midfs_lock_init( void )
{
    midfs_mutex = xSemaphoreCreateMutex();
}

/** 
* liffleFS call the sfud read port.
* none. 
* @param[in]   c:lfs_conifg struct , block:block address, off: address offset, buffer:read buffer, size:read size.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
int32_t midfs_lfs_read( const struct lfs_config *c, lfs_block_t block,  lfs_off_t off, void *buffer, lfs_size_t size )
{
    uint32_t addr = FS_START_ADDR + c->block_size * block + off;
    sfud_read( flash, addr, size, buffer );
    return 0;
}

/** 
* liffleFS call the sfud write port.
* none. 
* @param[in]   c:lfs_conifg struct , block:block address, off: address offset, buffer:write buffer, size:write size.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
static int32_t midfs_lfs_write( const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer,
                             lfs_size_t size )
{
    uint32_t addr = FS_START_ADDR +  c->block_size * block + off;
    sfud_write( flash, addr, size, buffer );
    return 0;
}

/** 
* liffleFS call the sfud erase port.
* none. 
* @param[in]   c:lfs_conifg struct , block:block address .
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
static int32_t midfs_lfs_erase( const struct lfs_config *c, lfs_block_t block )
{
    uint32_t addr = FS_START_ADDR +  c->block_size * block;
    sfud_erase( flash, addr, c->block_size );
    return 0;
}

/** 
* liffleFS call the sfud sync port.
* none. 
* @param[in]   c:lfs_conifg struct.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
static int32_t midfs_lfs_sync( const struct lfs_config *c )
{
    return 0;
}

/** 
* search the dirctory tree.
* none. 
* @param[in]   lfs: lfs struct, path;path.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
int midfs_lfs_ls( lfs_t *lfs, const char *path )
{
    lfs_dir_t dir;
    int err = lfs_dir_open( lfs, &dir, path );
    if( err )
    {
        return err;
    }
    struct lfs_info info;
    while( true )
    {
        int res = lfs_dir_read( lfs, &dir, &info );
        if( res < 0 )
        {
            return res;
        }
        if( res == 0 )
        {
            break;
        }
        midfs_log( "\t%s", info.name );
        switch( info.type )
        {
            case LFS_TYPE_REG:
                midfs_log( "\t\t%u Byte \r\n", info.size );
                break;
            case LFS_TYPE_DIR:
                midfs_log( "\t\t\tdir\r\n" );
                break;
            default:
                midfs_log( "?\r\n" );
                break;
        }
    }
    err = lfs_dir_close( lfs, &dir );
    if( err )
    {
        return err;
    }
    return 0;
}

const struct lfs_config lfs_cfg =
{
    // block device operations
    .read  = midfs_lfs_read,
    .prog  = midfs_lfs_write,
    .erase = midfs_lfs_erase,
    .sync  = midfs_lfs_sync,

    // block device configuration
    .read_size = 256,
    .prog_size = 256,
    .block_size = 4096,
    .block_count = LFSCFG_BLOCK_COUNT,
    .lookahead =  LFSCFG_LOOKAHEAD
};

/** 
* mount the file system.
* none. 
* @param[in]   none.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
void midfs_mount( void )

{
    FILE_HANDLER fp;
    int err;
    //HAL_Delay(5000);
    err = lfs_mount( &mid_fs, &lfs_cfg );
    if( !err )
    {
        err = midfs_fopen( &fp, FNAME_MARK_LFS_FORMAT, "r" );
        midfs_fclose(&fp);
    }
    // reformat if we can't mount the filesystem
    // this should only happen on the first boot
//		err = 1;
    if( err )
    {
        if( err < 0 )
            lfs_unmount( &mid_fs );
        midfs_log( "LittleFS start Format!!\r\n" );
        lfs_format( &mid_fs, &lfs_cfg );
        err = lfs_mount( &mid_fs, &lfs_cfg );
        midfs_fopen( &fp, FNAME_MARK_LFS_FORMAT, "w" );
        midfs_fclose(&fp);
    }
    if( err )
        midfs_log( "LittleFS mounte Fail(%d)!!\r\n", err );
    else
        midfs_log( "LittleFS mounted\r\n" );
    //ls();
}


//void midfs_check( void )
//{
//    uint32_t total = 0, used = 0;
////    SPIFFS_info( &mid_fs, &total, &used );
//    if( used > total )
//    {
//        //    SPIFFS_check( &fs );
//        //    SPIFFS_check( &fs );
//    }
//    midfs_usr( "midfs: used %d of %d Bytes\r\n", used, total );
//}

/** 
* print all the file infomation of root directory.
* none. 
* @param[in]   void.
* @param[out]  noen.
* @retval  none.
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
void midfs_ls( void )
{
    midfs_log( "\r\nfiles on [\\]\r\n" );
    midfs_lock( );
    midfs_lfs_ls( &mid_fs,  "/" );
    midfs_unlock( );
    midfs_log( "\r\n\r\n" );
}

/** 
* open file.
* none. 
* @param[in]   fp:open file hander, path:path of the file, mode:read write mode.
* @param[out]  noen.
* @retval  >0:open file ok, <0:open file failed
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
int midfs_fopen( FILE_HANDLER *fp, char *path, char *mode )
{
    int res = 0;
    uint32_t create = 0, modify = 0, state = 0;
    if( strstr( mode, "w" ) != 0 )
        create = 1;
    if( strstr( mode, "+" ) != 0 )
        modify = 1;
    if( create )
        state |= MIDFS_O_CREAT;
    if( modify )
        state |= MIDFS_O_MODIFY;
    if( state == 0 )
        state |= MIDFS_O_RDONLY;
#if (FS_USE_TYPE == FS_USE_SPIFFS)
    *fp = SPIFFS_open( &myfs.fs, path, state, 0 );
    if( *fp < 0 )
        res =  SPIFFS_errno( &myfs.fs );
#endif
#if (FS_USE_TYPE == FS_USE_LFS)
    midfs_lock();
    res = lfs_file_open( &mid_fs, fp, path, state );
    midfs_unlock();
    if( res )
        res = -1;
#endif
	midfs_log( "\nFOPEN(%s, %s) = %d\n", path, mode, res );
    return res;
}

/** 
* close file hander. 
* none. 
* @param[in]   fp:file hander.
* @param[out]  noen.
* @retval  read successful lenghth
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
int midfs_fclose( FILE_HANDLER *fp )
{
    int res = 0;
    midfs_log( "\nFCLOSE(fp:%d)\n", *fp );
#if (FS_USE_TYPE == FS_USE_SPIFFS)
    res =  SPIFFS_close( &myfs.fs, *fp );
#endif
#if (FS_USE_TYPE == FS_USE_LFS)
    midfs_lock();
    res = lfs_file_close( &mid_fs, fp );
    midfs_unlock();
#endif
    return res;
}

/** 
* read data from file. 
* none. 
* @param[in]   fp:file hander, size: read len, dst:data source.
* @param[out]  noen.
* @retval  read successful lenghth
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
uint32_t midfs_fread( FILE_HANDLER *fp, uint32_t size, void *dst )
{
    int ret = 0;
#if (FS_USE_TYPE == FS_USE_SPIFFS)
    ret = SPIFFS_read( &myfs.fs, *fp, dst, size );
#endif
#if (FS_USE_TYPE == FS_USE_LFS)
    midfs_lock();
    ret = lfs_file_read( &mid_fs, fp, dst, size );
    midfs_unlock();
#endif
	midfs_log( "\r\nFREAD(fp:%08x, %u) = %d b\r\n", fp, size, ret );
    return ret;
}

/** 
* write data to file. 
* none. 
* @param[in]   fp:file hander, size: write len, src:data source.
* @param[out]  noen.
* @retval  write successful lenghth
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
uint32_t midfs_fwrite( FILE_HANDLER *fp, uint32_t size, void *src )
{
    uint32_t ret = 0;
#if (FS_USE_TYPE == FS_USE_SPIFFS)
    ret = SPIFFS_write( &myfs.fs, *fp, src, size );
#endif
#if (FS_USE_TYPE == FS_USE_LFS)
    midfs_lock();
    ret = lfs_file_write( &mid_fs, fp, src, size );
    midfs_unlock();
#endif
	midfs_log( "\nFWRITE(fp:%08x, %d) = %d\n", fp, size, ret );
    return ret;
}

/** 
* seek file position. 
* none. 
* @param[in]   fp:file hander, offset:offset, from: start position.
* @param[out]  noen.
* @retval  file position
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
int32_t midfs_fseek( FILE_HANDLER *fp, uint32_t offset, uint32_t from )
{
    uint32_t p;
    switch( from )
    {
        case SEEK_SET:
            from = MIDFS_SEEK_SET;
            break;
        case SEEK_CUR:
            from = MIDFS_SEEK_CUR;
            break;
        case SEEK_END:
            from = MIDFS_SEEK_END;
            break;
        default:
            return -1;
    }
#if (FS_USE_TYPE == FS_USE_SPIFFS)
    p = SPIFFS_lseek( &myfs.fs, *fp, offset, from );
#endif
#if (FS_USE_TYPE == FS_USE_LFS)
    midfs_lock();
    p = lfs_file_seek( &mid_fs, fp, offset, from );
    midfs_unlock();
#endif
	midfs_log( "\nFSEEK(fp:%08x, %d, %d) = %d\n", fp, offset, from, p );
    return p;
}

/** 
* read file size. 
* read file size from SPI flash. 
* @param[in]   fp:file hander.
* @param[out]  noen.
* @retval  file size in byte
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
uint32_t midfs_fsize( FILE_HANDLER *fp )
{
    uint32_t ret;
    ret = midfs_fseek( fp, 0, SEEK_END );
	midfs_log( "\nFSIZE(fp:%d) = %d\n", fp, ret );
    return ret;
}

/** 
* delete file. 
* delete file from SPI flash. 
* @param[in]   fname:file name string.
* @param[out]  noen.
* @retval  0 success, others failed
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
int midfs_fremove( char *fname )
{
    int res = 0;
#if (FS_USE_TYPE == FS_USE_SPIFFS)
    res = SPIFFS_remove( &myfs.fs, fname );
#endif
#if (FS_USE_TYPE == FS_USE_LFS)
    midfs_lock();
    res = lfs_remove( &mid_fs, fname );
    midfs_unlock();
#endif
    return res;
}

/** 
* midfs initial. 
* if the spi flash file system had not formated, format it and mount. 
* @param[in]   fname:file name string.
* @param[out]  noen.
* @retval  0 success, others failed
* @par TAG 
*      reserved 
* @par other 
*      none 
* @par modify
*      ken 2019-01-07 create
*/
void mid_fs_init( void )
{
	fs_spi_init();
    if( sfud_init() == SFUD_SUCCESS )
    {
        flash = sfud_get_device_table() + 0;
#ifdef SPIFLASH_TEST
        sfud_test( 111, sizeof( sfud_test_buf ), sfud_test_buf );
#endif
        midfs_lock_init();
        midfs_mount();
//        midfs_check();
		
        midfs_ls();
        midfs_log( "MID FS init done!\r\n" );
    }
}




const struct lfs_config lfs_cfg 将sfud的操作接口影射到lifffs读写函数,重建midfs_open,midfs_close,midfs_read,midfs_write等用户操作函数,在多任务工作下,关键地方使用的互斥量
源码打包下载:https://download.csdn.net/download/dmjkun/10956215

你可能感兴趣的:(FreeRTOS,littlefs,sfud)