完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
LittleFS是ARM mbedOS的官方推荐文件系统,具有轻量级,掉电安全的特性。文件系统移植 首先去Github上下载最新发型版本的LittleFs源码,我下载的是V2.2.1版本,并阅读README文档了解移植详情,因为README.md文档讲解很有限,所以下面会在移植过程中做出补充。在工程中添加文件系统如下: 以上两个文件在文件系统源码根目录下;移植要点
lfs_config为移植的重中之重,定义在lfs.h中: // Configuration provided during initialization of the littlefs struct lfs_config { // 用于传递信息给块设备,便于块设备驱动进行特定的处理,比如:告诉块设备驱动 // 具体哪个范围用于文件系统(传参); // 这个内容的数据结构由块设备驱动来定义; void *context; // 从指定块内读数据 // int (*read)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); // 写块接口,用于将一段数据写入到块中,这个块必须是已经被擦除的 //(文件系统会确保擦除) int (*prog)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size); //擦除一个块 int (*erase)(const struct lfs_config *c, lfs_block_t block); // Sync the state of the underlying block device. Negative error codes // are propogated to the user.(可以直接写空) int (*sync)(const struct lfs_config *c); // 最小读取字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗) lfs_size_t read_size; // 最小写入字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗) lfs_size_t prog_size; //擦除块字节数 不会影响内存消耗;这个数值可以比物理擦除地址大,但是这个数值应该尽可能小, //因为每个文件至少占用一个块;值必须是读取和编程粒度的整数倍; lfs_size_t block_size; // 可以被擦除的块数量,取决于设备容量 lfs_size_t block_count; //littlefs逐出元数据日志并将元数据移动到另一个块之前的擦除周期数。 建议值在 //100-1000范围内,较大的值具有较好的性能,但是会导致磨损分布不均匀。 // -1 禁用块级磨损均衡 int32_t block_cycles; // Size of block caches. Each cache buffers a portion of a block in RAM. // The littlefs needs a read cache, a program cache, and one additional // cache per file. Larger caches can improve performance by storing more // data and reducing the number of disk accesses. Must be a multiple of // the read and program sizes, and a factor of the block size. //块缓存的大小。 每个缓存都会在RAM中缓冲一部分块。littlefs需要一个读缓存, //一个程序缓存以及每个文件一个额外的缓存。 更大的缓存可以通过存储更多数据 //来减少磁盘访问次数来提高性能。 //该值必须是读取和编程大小的倍数,并且是块大小的因数。 lfs_size_t cache_size; // 块分配时的预测深度(分配块时每次步进多少个块),这个数值必须为8的整数倍, //如1024表示每次预测1024个block。这个值对于内存消耗影响不大 lfs_size_t lookahead_size; // Optional statically allocated read buffer. Must be cache_size. // By default lfs_malloc is used to allocate this buffer. void *read_buffer; // Optional statically allocated program buffer. Must be cache_size. // By default lfs_malloc is used to allocate this buffer. void *prog_buffer; // Optional statically allocated lookahead buffer. Must be lookahead_size // and aligned to a 32-bit boundary. By default lfs_malloc is used to // allocate this buffer. void *lookahead_buffer; // Optional upper limit on length of file names in bytes. No downside for // larger names except the size of the info struct which is controlled by // the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in // superblock and must be respected by other littlefs drivers. lfs_size_t name_max; // Optional upper limit on files in bytes. No downside for larger files // but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored // in superblock and must be respected by other littlefs drivers. lfs_size_t file_max; // Optional upper limit on custom attributes in bytes. No downside for // larger attributes size but must be <= LFS_ATTR_MAX. Defaults to // LFS_ATTR_MAX when zero. lfs_size_t attr_max; }; read接口解析 /* * @brief 从指定块内读数据 * @param [in] lfs_config格式参数; * @param [in] block 逻辑块编号,从0开始 * @param [in] off 块内偏移,lfs在调用read接口时,传入的off值一定能被read_size整除 * @param [out] 读出数据的输出缓冲区 * @param [in] size 要读取的字节数,lfs在读取时会确保不会跨块; * @retval 0 成功 <0 错误码 */ int (*read)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); write接口解析 /* * @brief 从指定块内读数据 * @param [in] lfs_config格式参数; * @param [in] block 逻辑块编号,从0开始 * @param [in] off 块内偏移,lfs在调用prog接口时,传入的off值一定能被rprog_size整除 * @param [in] 写入数据的缓冲区 * @param [in] size 要读取的字节数,lfs在读取时会确保不会跨块; * @retval 0 成功 <0 错误码 */ int (*prog)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size); erase接口解析 /* * @brief 从指定块内读数据 * @param [in] lfs_config格式参数; * @param [in] block 要擦除的逻辑块编号,从0开始 * @retval 0 成功 <0 错误码 */ int (*erase)(const struct lfs_config *c, lfs_block_t block); 上述接口需要根据想要移植的特定设备进行编写;lfs的动态内存 lfs同时支持静态和动态内存两种方式,使用LFS_NO_MALLOC来进行开启关闭,当未定义LFS_NO_MALLOC时,用户需要提供自己的内存申请以及释放函数,接口在lfs_util.h中定义: // Allocate memory, only used if buffers are not provided to littlefs // Note, memory must be 64-bit aligned static inline void *lfs_malloc(size_t size) { #ifndef LFS_NO_MALLOC return mymalloc(SRAMIN,size); //用户申请内存函数 #else (void)size; return NULL; #endif } // Deallocate memory, only used if buffers are not provided to littlefs static inline void lfs_free(void *p) { #ifndef LFS_NO_MALLOC myfree(SRAMIN,p); //用户释放内存函数 #else (void)p; #endif } 如果用户不支持动态内存,则需要定义LFS_NO_MALLOC,并且需要在lfs_config结构体中给read_buffer/prog_buffer/lookahead_buffer/file_buffer设置静态内存,并且同一时刻只能打开一个文件(实例);测试实例 我基于正点原子STM32F1精英版V1.41开发板进行了littleFS的移植,并且同时支持了STM32内部Flash和外部的W25Q128,项目地址为 : 基于正点原子STM32F1精英版的LittleFS移植 项目测试例如下所示: /* lfs for STM32Flash ********************************************************/ lfs_t lfs_Stm32Flash; lfs_file_t file_Stm32Flash; // configuration of the filesystem is provided by this struct const struct lfs_config cfg_Stm32Flash = { // block device operations .read = stm32flash_readLittlefs, .prog = stm32flash_writeLittlefs, .erase = stm32flash_eraseLittlefs, .sync = stm32flash_syncLittlefs, // block device configuration .read_size = 128, .prog_size = 128, .block_size = STM32Flash_ERASE_GRAN, .block_count = STM32Flash_NUM_GRAN/2, .cache_size = 512, .lookahead_size = 512, .block_cycles = 500, }; extern void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite); int main(void) { int err = -1; delay_init(); //ÑÓʱº¯Êý³õʼ»¯ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÉèÖÃÖжÏÓÅÏȼ¶·Ö×éΪ×é2£º2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶ uart_init(115200); //´®¿Ú³õʼ»¯Îª115200 LED_Init(); //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú KEY_Init(); //°´¼ü³õʼ»¯ W25QXX_Init(); //W25QXX³õʼ»¯ while(W25QXX_ReadID()!=W25Q128) //¼ì²â²»µ½W25Q128 { printf("W25Q128 Check Failed!rn"); delay_ms(500); printf("Please Check! rn"); delay_ms(500); LED0=!LED0;//DS0ÉÁ˸ } printf("W25Q128 Ready!rn"); // err = lfs_mount(&lfs, &cfg); // // if(err ) // { // lfs_format(&lfs, &cfg); // lfs_mount(&lfs, &cfg); // } // err = lfs_mount(&lfs_Stm32Flash, &cfg_Stm32Flash); if( err ) { lfs_format(&lfs_Stm32Flash, &cfg_Stm32Flash); lfs_mount(&lfs_Stm32Flash, &cfg_Stm32Flash); } while(1) { LED0=!LED0; uint32_t boot_count = 0; lfs_file_open(&lfs_Stm32Flash, &file_Stm32Flash, "boot_count", LFS_O_RDWR | LFS_O_CREAT); lfs_file_read(&lfs_Stm32Flash, &file_Stm32Flash, &boot_count, sizeof(boot_count)); // update boot count boot_count += 1; lfs_file_rewind(&lfs_Stm32Flash, &file_Stm32Flash); // seek the file to begin lfs_file_write(&lfs_Stm32Flash, &file_Stm32Flash, &boot_count, sizeof(boot_count)); // remember the storage is not updated until the file is closed successfully lfs_file_close(&lfs_Stm32Flash, &file_Stm32Flash); // // release any resources we were using // lfs_unmount(&lfs); // print the boot count printf("boot_count: %dn", boot_count); delay_ms(20000); } } 下载运行后串口打印效果如下: 工程移植到此完成,接口的优化后面有时间再写。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1936浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
729浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
569浏览 3评论
594浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
552浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 19:44 , Processed in 0.565563 second(s), Total 40, Slave 33 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号