MM32F3273G8P火龙果开发板MindSDK开发教程19 - littlefs文件系统的移植
1、littlefs简介
LittleFS 由ARM官方发布,ARM mbedOS的官方推荐文件系统,具有轻量级,掉电安全的特性。主要用在微控制器和flash上,特点如下:
掉电恢复,在写入时即使复位或者掉电也可以恢复到上一个正确的状态。
擦写均衡,有效延长flash的使用寿命。例如W25QXX系列的spi接口的flash,擦写次数大概在10万次,如果是操作flash比较频繁那么这10万次很快就会到达上限从而导致芯片废掉。
有限的RAM/ROM,相对于FATFS节省ROM和RAM空间
github传送门
2、littlefs移植
上一节我们移植了sfud库,可以对spi flash进行读写操作。但是没有文件系统,就没有文件的概念。
这节,我们在上一节的基础上,再移植littlefs文件系统。
下载解压源码包,将如下几个文件拷贝到我们的工程。
并且增加ifs_port.c文件,工程视图如下:
ifs_port.c内容如下,里面的读写函数其实调用的是sfud中的读写函数。
/* lfs_port.c */
#include "lfs.h"
#include "sfud.h"
int lfs_flash_init( struct lfs_config *c);
static int lfs_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
static int lfs_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);
static int lfs_flash_erase(const struct lfs_config *c, lfs_block_t block);
static int lfs_flash_sync(const struct lfs_config *c);
int lfs_flash_init(struct lfs_config *c)
{
sfud_init(); /* init sfud. */
const sfud_flash *flash = sfud_get_device(0u);
c->read = lfs_flash_read;
c->prog = lfs_flash_prog;
c->erase = lfs_flash_erase;
c->sync = lfs_flash_sync;
c->read_size = 16;
c->prog_size = 16;
//c->block_size = LFS_FLASH_SECTOR_SIZE;
c->block_size = flash->chip.erase_gran;
c->block_count = 256;
c->block_cycles = 500;
c->cache_size = 16;
c->lookahead_size = 16;
//c->read_buffer = (void *)lfs_flash_read_buf;
//c->prog_buffer = (void *)lfs_flash_prog_buf;
//c->lookahead_buffer = (void *)lfs_flash_lookahead_buf;
return LFS_ERR_OK;
}
static int lfs_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
{
uint32_t addr = block * c->block_size + off;
const sfud_flash *flash = sfud_get_device(0u);
sfud_read(flash, addr, size, (uint8_t *)buffer);
return LFS_ERR_OK;
}
static int
lfs_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
uint32_t addr = block * c->block_size + off;
const sfud_flash *flash = sfud_get_device(0u);
sfud_write(flash, addr, size, (uint8_t *)buffer);
return LFS_ERR_OK;
}
static int lfs_flash_erase(const struct lfs_config *c, lfs_block_t block)
{
const sfud_flash *flash = sfud_get_device(0u);
sfud_erase(flash, block * c->block_size, c->block_size);
return LFS_ERR_OK;
}
static int lfs_flash_sync(const struct lfs_config *c)
{
return LFS_ERR_OK;
}
/* EOF. */
3、调用与测试
创建一个文件,写入一个值,每次开机+1,然后看是否每次开机后的值会+1。
#include <stdint.h>
#include <stdio.h>
#include "clock_init.h"
#include "hal_rcc.h"
#include "hal_gpio.h"
#include "hal_uart.h"
#include "led.h"
#include "uart.h"
#include "systick.h"
#include "key.h"
#include "timer.h"
#include "multi_button.h"
#include "spi.h"
#include "sfud.h"
#include "lfs.h"
lfs_t app_lfs;
lfs_file_t app_lfs_file;
struct lfs_config app_lfs_config;
int lfs_flash_init(struct lfs_config *c);
struct Button btn1;
void BTN1_PRESS_DOWN_Handler(void* btn)
{
//do something...
printf("BTN1_PRESS_DOWN_Handler \r\n");
}
void BTN1_PRESS_UP_Handler(void* btn)
{
//do something...
printf("BTN1_PRESS_UP_Handler \r\n");
}
int main(void)
{
BOARD_InitBootClocks(); // ³õʼ»¯Ê±ÖÓ
BOARD_InitDebugConsole();
BOARD_UserKeyInit();
LED_Init();
BOARD_TIM6_Init();
// for mutilbutton init
button_init(&btn1, read_button_GPIO, 0, btn1_id);
button_attach(&btn1, PRESS_DOWN, BTN1_PRESS_DOWN_Handler);
button_attach(&btn1, PRESS_UP, BTN1_PRESS_UP_Handler);
button_start(&btn1);
BOARD_TIM7_Init();
BOARD_Delay1Ms(1000);
printf("Board Init Success\r\n");
printf("spi_lfs_sfud_spi example.\r\n");
int err = lfs_flash_init(&app_lfs_config);
if (err)
{
printf("lfs_flash_init() failed.\r\n");
while (1);
}
err = lfs_mount(&app_lfs, &app_lfs_config);
if (err)
{
printf("lfs_mount() failed.\r\n");
lfs_format(&app_lfs, &app_lfs_config);
printf("lfs_format() done.\r\n");
lfs_mount(&app_lfs, &app_lfs_config);
printf("lfs_mount() done.\r\n");
}
// read current count
uint32_t boot_count = 0;
lfs_file_open(&app_lfs, &app_lfs_file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&app_lfs, &app_lfs_file, &boot_count, sizeof(boot_count));
// update boot count
boot_count += 1;
lfs_file_rewind(&app_lfs, &app_lfs_file);
lfs_file_write(&app_lfs, &app_lfs_file, &boot_count, sizeof(boot_count));
// remember the storage is not updated until the file is closed successfully
lfs_file_close(&app_lfs, &app_lfs_file);
// release any resources we were using
lfs_unmount(&app_lfs);
// print the boot count
printf("boot_count: %u\r\n", (unsigned)boot_count);
while(1)
{
}
}
4、现象
代码
代码下载