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.youkuaiyun.com/download/dmjkun/10956215

DSP和标准外设库: 资源编号 : STSW-STM32065 资源名称 : STM32F4 DSP and standard peripherals library 文件名 : stm32_f105-07_f2_f4_usb-host-device_lib.zip 下载地址 : http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257901# USB库: 资源编号 : STSW-STM32046 资源名称 : STM32F105/7, STM32F2 and STM32F4 USB on-the-go Host and device library (UM1021) 文件名 : stm32_f105-07_f2_f4_usb-host-device_lib.zip 下载地址 : http://www.st.com/web/en/catalog/tools/PF257882 ETH以太网库: 资源编号 : STSW-STM32046 资源名称 : LwIP TCP/IP stack demonstration for STM32F4x7 microcontrollers (AN3966) 文件名 : stsw-stm32070.zip 下载地址 : http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257906 【CMSIS】 Cortex微控制器软件接口程序(Cortex Microcontroller Software Interface Standard (CMSIS). ) 版本: V4.2 发布日期: 31. July 2014 【STM32F4xx_StdPeriph_Driver】 STM32F40x系列CPU标准外设驱动程序 版本: V1.5.0 发布日期: 06-March-2015 【STM32_USB_OTG_Driver】 STM32F105/7xx, STM32F2xx and STM32F4xx USB Device Library 版本: V2.1.0 发布日期: 2012-03-19 【STM32_USB_Device_Library】 STM32F105/7xx, STM32F2xx and STM32F4xx USB Device Library 版本: V1.1.0 发布日期: 2012-03-05 【STM32_USB_HOST_Library】 STM32F105/7xx, STM32F2xx and STM32F4xx USB Host Library 版本: V2.1.0 发布日期: 2012-03-19 【STM32F4x7_ETH_Driver】 STM32F4x7 Eth Library 版本: V1.1.0 发布日期: 31-July-2013 ********************************************************************************************************* * * 版 本 : V1.0 * 说 明 : 本实验主要实现FreeRTOS+STemWin+FatFS+USB Host综合 * 实验目的: * 1. 学习FreeRTOS+STemWin+FatFS+USB Host综合 * 2. 这里的USB Host主要实现U盘相关处理,支持U盘热插拔。 * 用户可以根据需要在usb_usr.c文件中的插入检测函数: * USBH_USR_Configuration_DescAvailable或者函数USBH_USR_Init函数加入插入标志 * 拔出检测函数: * USBH_USR_DeviceDisconnected * 实验内容: * 1. 按下按键K1可以通过串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1) * ================================================= * 任务名 任务状态 优先级 剩余栈 任务序号 * vTaskUserIF R 2 272 2 * vTaskGUI R 1 657 1 * IDLE R 0 113 6 * vTaskMsgPro B 4 1957 4 * vTaskLED B 3 483 3 * vTaskStart B 5 489 5 * * * 任务名 运行计数 使用率 * vTaskUserIF 5583 1% * vTaskGUI 10782 2% * IDLE 355589 91% * vTaskLED 0 <1% * vTaskMsgPro 16770 4% * vTaskStart 17 <1% * 串口软件建议使用SecureCRT(V6光盘里面有此软件)查看打印信息。 * 各个任务实现的功能如下: * vTaskGUI 任务: emWin任务 * vTaskTaskUserIF 任务: 接口消息处理 * vTaskLED 任务: LED闪烁 * vTaskMsgPro 任务: U盘中文件处理和浏览 * vTaskStart 任务: 启动任务,也就是最高优先级任务,这里实现按键扫描和触摸检测 * 2. 任务运行状态的定义如下,跟上面串口打印字母B, R, D, S对应: * #define tskBLOCKED_CHAR ( 'B' ) 阻塞 * #define tskREADY_CHAR ( 'R' ) 就绪 * #define tskDELETED_CHAR ( 'D' ) 删除 * #define tskSUSPENDED_CHAR ( 'S' ) 挂起 * 3. 本实验的USB Host主要是对U盘的操作,通过电脑端的串口软件SecureCRT软件, * 给板子发送相关命令实现操作,具体实现在demo_fatfs文件里面。 * printf("请选择操作命令:\r\n"); * printf("1 - 显示根目录下的文件列表\r\n"); * printf("2 - 创建一个新文件armfly.txt\r\n"); * printf("3 - 读armfly.txt文件的内容\r\n"); * printf("4 - 创建目录\r\n"); * printf("5 - 删除文件和目录\r\n"); * printf("6 - 读写文件速度测试\r\n"); * printf("7 - 挂载U盘\r\n"); * printf("8 - 卸载U盘\r\n"); * 注意事项: * 1. 本实验推荐使用串口软件SecureCRT,要不串口打印效果不整齐。此软件在 * V5开发板光盘里面有。 * 2. 务必将编辑器的缩进参数和TAB设置为4来阅读本文件,要不代码显示不整齐。 * * 修改记录 : * 版本号 日期 作者 说明 * V1.0 2016-03-15 Eric2013 1. ST固件库到V1.5.0版本 * 2. BSP驱动包V1.2 * 3. FreeRTOS版本V8.2.3 * 4. STemWin版本V5.28 * 5. FatFS版本V0.11a * * Copyright (C), 2016-2020, 安富莱电子 www.armfly.com * *********************************************************************************************************
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵向深耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值