想要使用片内flash挂载文件系统需要如下操作
1.添加fal和littlefs软件包
2.打开DFS组件
3.打开MTD Nor flash设备驱动程序
4.board.h中打开 #define BSP_USING_ON_CHIP_FLASH
5.添加drv_flash_l4.c
6.fal_cfg.h中添加/修改FAL_FLASH_DEV_TABLE,对应drv_flash_l4.c中的stm32_onchip_flash
7.修改FAL_PART_TABLE,配置空间区域和区域名,通常app是应用程序占空,剩下的可作为文件系统使用,实测32k以上是可行的
//-------------fal_cfg.h-----------------------------
extern const struct fal_flash_dev stm32_onchip_flash; extern struct fal_flash_dev nor_flash0; /* flash device table */ #define FAL_FLASH_DEV_TABLE \ { \ &stm32_onchip_flash, \ } /* ====================== Partition Configuration ========================== */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WORD, "app", "onchip_flash", 0, 480*1024, 0}, \ {FAL_PART_MAGIC_WORD, "fs", "onchip_flash", 480*1024, 32*1024, 0}, \ } #endif /* FAL_PART_HAS_TABLE_CFG */
littlefs和fal软件包配置如下
遇到的问题
格式化扇区是提示擦除失败,如下
[E/FAL] (fal_partition_erase:476) Partition erase error! Flash device(onchip_flash) erase error!
问题在drv_flash_l4.c中的stm32_flash_erase函数返回错误导致
最后发现是在进行flash erase操作是单片机发生PGSERR错误,原因暂不清楚,通过擦除的重试操作解决了此问题,代码如下
int stm32_flash_erase(rt_uint32_t addr, size_t size)
{
rt_err_t result = RT_EOK;
uint8_t err;
uint32_t FirstPage = 0, NbOfPages = 0, BankNumber = 0;
uint32_t PAGEError = 0;
if ((addr + size) > STM32_FLASH_END_ADDRESS)
{
LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void*)(addr + size));
return -RT_EINVAL;
}
/*Variable used for Erase procedure*/
FLASH_EraseInitTypeDef EraseInitStruct;
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Clear OPTVERR bit set on virgin samples */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
/* Get the 1st page to erase */
FirstPage = GetPage(addr);
/* Get the number of pages to erase from 1st page */
NbOfPages = GetPage(addr + size - 1) - FirstPage + 1;
/* Get the bank */
BankNumber = GetBank(addr);
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Banks = BankNumber;
EraseInitStruct.Page = FirstPage;
EraseInitStruct.NbPages = NbOfPages;
err = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError); if (err != HAL_OK)//retry { err = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError); }
if (err != HAL_OK)
{
result = -RT_ERROR;
goto __exit;
}
__exit:
HAL_FLASH_Lock();
if (result != RT_EOK)
{
// LOG_D("erase :size:%d",size);
// LOG_E("erase err: size=%d,%d(%d)", size,result,err);
return result;
}
LOG_D("erase done: addr (0x%p), size %d", (void*)addr, size);
return size;
}
文件系统初始化代码如下
#define FS_PARTITION_NAME "fs" void littlefs_sample(void) { struct rt_device *mtd_dev = RT_NULL; // 初始化 fal fal_init(); // 创建 mtd 设备 mtd_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME); if (!mtd_dev) { LOG_E("Can't create a mtd device on '%s' partition.", FS_PARTITION_NAME); } else { // 挂载littlefs // 参数: 块设备名、文件系统挂载点路径,挂载文件系统类型,读写标志位,文件系统的私有数据 if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == 0) { LOG_I("para initialized!"); //readwrite_sample(); } else // dfs_mkfs("elm", "AT45"); { LOG_E("dfs_mount Failed "); /* 格式化文件系统 */ dfs_mkfs("lfs", FS_PARTITION_NAME); /* 挂载 littlefs */ if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == 0) { LOG_I("para initialized!"); } else { LOG_E("Failed to initialize filesystem!"); } } } }
测试成功
msh />ls
Directory /:
msh />df
disk free: 28.0 KB [ 14 block, 2048 bytes per block ]
msh />