上期帶大家了解了FAL組件和DFS文件系統的功能特點和使用方法,本期將繼續解讀如何將EasyFlsh移植到FAL分區。
簡述EasyFlash
關于EasyFlash的來源我們已經講過,EasyFlash是一款開源的輕量級嵌入式Flash存儲器庫,方便開發者更加輕松的實現基于Flash存儲器的常見應用開發。非常適合智能家居、可穿戴、工控、醫療、物聯網等需要斷電存儲功能的產品,資源占用極低,支持各種 MCU 片上存儲器。EasyFlash不僅能夠實現對產品的設定參數或運行日志等信息的掉電保存功能,還封裝了簡潔的增加、刪除、修改及查詢方法,降低了開發者對產品參數的處理難度,也保證了產品在后期升級時擁有更好的擴展性。讓Flash變為NoSQL(非關系型數據庫)模型的小型鍵值(Key-Value)存儲數據庫。
EasyFlash軟件包使用
打開ENV進入路徑:RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.,選擇軟件包版本為最新版。配置后退出ENV,同時使用pkgs --update下載軟件包,然后再使用scons-target=mdk5重新生成MDK5文件。
移植EasyFlash
下載完easyflash軟件包后,我們復制. t-threadsplpc55sxxlpc55s69_nxp_evkpackagesEasyFlash-latestportsef_fal_port.c到目錄. t-threadsplpc55sxxlpc55s69_nxp_evkoardportseasyflashef_fal_port.c,雙擊打開該文件,完成以下修改:
// 修改 FAL_EF_PART_NAME 為 easyflash
#define FAL_EF_PART_NAME "easyflash"
編寫EasyFlash測試用例
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-04-21 Wangyuqiang the first version
*/
#include "rtthread.h"
#include "rtdevice.h"
#include "board.h"
#include "fal.h"
#include
#include "easyflash.h"
#include
#define FS_PARTITION_NAME "filesystem"
#define BUF_SIZE 1024
static int fal_test(const char *partiton_name)
{
int ret;
int i, j, len;
uint8_t buf[BUF_SIZE];
const struct fal_flash_dev *flash_dev = RT_NULL;
const struct fal_partition *partition = RT_NULL;
if (!partiton_name)
{
rt_kprintf("Input param partition name is null!
");
return -1;
}
partition = fal_partition_find(partiton_name);
if (partition == RT_NULL)
{
rt_kprintf("Find partition (%s) failed!
", partiton_name);
ret = -1;
return ret;
}
flash_dev = fal_flash_device_find(partition->flash_name);
if (flash_dev == RT_NULL)
{
rt_kprintf("Find flash device (%s) failed!
", partition->flash_name);
ret = -1;
return ret;
}
rt_kprintf("Flash device : %s "
"Flash size : %dK
"
"Partition : %s "
"Partition size: %dK
",
partition->flash_name,
flash_dev->len/1024,
partition->name,
partition->len/1024);
/* erase all partition */
ret = fal_partition_erase_all(partition);
if (ret < 0)
{
rt_kprintf("Partition (%s) erase failed!
", partition->name);
ret = -1;
return ret;
}
rt_kprintf("Erase (%s) partition finish!
", partiton_name);
/* read the specified partition and check data */
for (i = 0; i < partition->len;)
{
rt_memset(buf, 0x00, BUF_SIZE);
len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
ret = fal_partition_read(partition, i, buf, len);
if (ret < 0)
{
rt_kprintf("Partition (%s) read failed!
", partition->name);
ret = -1;
return ret;
}
for(j = 0; j < len; j++)
{
if (buf[j] != 0xFF)
{
rt_kprintf("The erase operation did not really succeed!
");
ret = -1;
return ret;
}
}
i += len;
}
/* write 0x00 to the specified partition */
for (i = 0; i < partition->len;)
{
rt_memset(buf, 0x00, BUF_SIZE);
len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
ret = fal_partition_write(partition, i, buf, len);
if (ret < 0)
{
rt_kprintf("Partition (%s) write failed!
", partition->name);
ret = -1;
return ret;
}
i += len;
}
rt_kprintf("Write (%s) partition finish! Write size %d(%dK).
", partiton_name, i, i/1024);
/* read the specified partition and check data */
for (i = 0; i < partition->len;)
{
rt_memset(buf, 0xFF, BUF_SIZE);
len = (partition->len - i) > BUF_SIZE ? BUF_SIZE : (partition->len - i);
ret = fal_partition_read(partition, i, buf, len);
if (ret < 0)
{
rt_kprintf("Partition (%s) read failed!
", partition->name);
ret = -1;
return ret;
}
for(j = 0; j < len; j++)
{
if (buf[j] != 0x00)
{
rt_kprintf("The write operation did not really succeed!
");
ret = -1;
return ret;
}
}
i += len;
}
ret = 0;
return ret;
}
static void fal_sample(void)
{
/* 1- init */
fal_init();
if (fal_test("font") == 0)
{
rt_kprintf("Fal partition (%s) test success!
", "font");
}
else
{
rt_kprintf("Fal partition (%s) test failed!
", "font");
}
if (fal_test("download") == 0)
{
rt_kprintf("Fal partition (%s) test success!
", "download");
}
else
{
rt_kprintf("Fal partition (%s) test failed!
", "download");
}
}
MSH_CMD_EXPORT(fal_sample, fal sample);
static void fal_elmfat_sample(void)
{
int fd, size;
struct statfs elm_stat;
struct fal_blk_device *blk_dev;
char str[] = "elmfat mount to W25Q flash.", buf[80];
/* fal init */
fal_init();
/* create block device */
blk_dev = (struct fal_blk_device *)fal_blk_device_create(FS_PARTITION_NAME);
if(blk_dev == RT_NULL)
rt_kprintf("Can't create a block device on '%s' partition.
", FS_PARTITION_NAME);
else
rt_kprintf("Create a block device on the %s partition of flash successful.
", FS_PARTITION_NAME);
/* make a elmfat format filesystem */
if(dfs_mkfs("elm", FS_PARTITION_NAME) == 0)
rt_kprintf("make elmfat filesystem success.
");
/* mount elmfat file system to FS_PARTITION_NAME */
if(dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0)
rt_kprintf("elmfat filesystem mount success.
");
/* Get elmfat file system statistics */
if(statfs("/", &elm_stat) == 0)
rt_kprintf("elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.
",
elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree);
if(mkdir("/user", 0x777) == 0)
rt_kprintf("make a directory: '/user'.
");
rt_kprintf("Write string '%s' to /user/test.txt.
", str);
/* Open the file in create and read-write mode, create the file if it does not exist*/
fd = open("/user/test.txt", O_WRONLY | O_CREAT);
if (fd >= 0)
{
if(write(fd, str, sizeof(str)) == sizeof(str))
rt_kprintf("Write data done.
");
close(fd);
}
/* Open file in read-only mode */
fd = open("/user/test.txt", O_RDONLY);
if (fd >= 0)
{
size = read(fd, buf, sizeof(buf));
close(fd);
if(size == sizeof(str))
rt_kprintf("Read data from file test.txt(size: %d): %s
", size, buf);
}
}
MSH_CMD_EXPORT_ALIAS(fal_elmfat_sample, fal_elmfat,fal elmfat sample);
static void easyflash_sample(void)
{
/* fal init */
fal_init();
/* easyflash init */
if(easyflash_init() == EF_NO_ERR)
{
uint32_t i_boot_times = NULL;
char *c_old_boot_times, c_new_boot_times[11] = {0};
/* get the boot count number from Env */
c_old_boot_times = ef_get_env("boot_times");
/* get the boot count number failed */
if (c_old_boot_times == RT_NULL)
c_old_boot_times[0] = '0';
i_boot_times = atol(c_old_boot_times);
/* boot count +1 */
i_boot_times ++;
rt_kprintf("===============================================
");
rt_kprintf("The system now boot %d times
", i_boot_times);
rt_kprintf("===============================================
");
/* interger to string */
sprintf(c_new_boot_times, "%d", i_boot_times);
/* set and store the boot count number to Env */
ef_set_env("boot_times", c_new_boot_times);
ef_save_env();
}
}
MSH_CMD_EXPORT(easyflash_sample, easyflash sample);
EasyFlash測試結果
打開串口助手,輸入命令:-
msh />easyflash_sample
復制代碼
第一次命令調用:第二次RESET開發板后調用:
結語
至此,FAL分區管理EasyFlash變量管理已經全部介紹完畢了,經歷從移植軟件模擬SPI框架到LPC55S69,到移植過程中不斷遇到的問題,解決問題并提供應用示例,并完成開發日記、開發筆記及應用教學,作者坦言整個過程還是受益良多的。希望大家懷揣著一顆求知及授學之心,共同建設好這個領域!參考資料:
本文轉載自:END
更多恩智浦AI-IoT市場和產品信息,邀您同時關注“NXP客棧”微信公眾號
? ? ?NXP客棧
恩智浦致力于打造安全的連接和基礎設施解決方案,為智慧生活保駕護航。
長按二維碼,關注我們
恩智浦MCU加油站
這是由恩智浦官方運營的公眾號,著重為您推薦恩智浦MCU的產品信息、開發技巧、教程文檔、培訓課程等內容。
長按二維碼,關注我們
原文標題:【LPC55S69】使用FAL分區管理與easyflash變量管理(下集)
文章出處:【微信公眾號:恩智浦MCU加油站】歡迎添加關注!文章轉載請注明出處。
-
mcu
+關注
關注
146文章
17310瀏覽量
352193 -
恩智浦
+關注
關注
14文章
5877瀏覽量
108077
原文標題:【LPC55S69】使用FAL分區管理與easyflash變量管理(下集)
文章出處:【微信號:NXP_SMART_HARDWARE,微信公眾號:恩智浦MCU加油站】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論