在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用FAL分區管理與easyflash變量管理

RT-Thread官方賬號 ? 2024-10-01 08:10 ? 次閱讀

1.

FAL組件

1.1

什么是FAL

FAL (Flash Abstraction Layer) Flash 抽象層,是對 Flash 及基于 Flash 的分區進行管理、操作的抽象層,對上層統一了 Flash 及 分區操作的 API (框架圖如下所示),并具有以下特性:

支持靜態可配置的分區表,并可關聯多個 Flash 設備;

分區表支持 自動裝載 。避免在多固件項目,分區表被多次定義的問題;

代碼精簡,對操作系統 無依賴 ,可運行于裸機平臺,比如對資源有一定要求的 Bootloader;

統一的操作接口。保證了文件系統、OTA、NVM(例如:EasyFlash https://github.com/armink-rtt-pkgs/EasyFlash) 等對 Flash 有一定依賴的組件,底層 Flash 驅動的可重用性;

自帶基于 Finsh/MSH 的測試命令,可以通過 Shell 按字節尋址的方式操作(讀寫擦) Flash 或分區,方便開發者進行調試、測試;

976db67c-7f89-11ef-bb4b-92fbcf53809c.png

通過上圖我們也可以清晰明了了,看到,FAL抽象層向下可以通過Flash硬件進行統一管理,當然也可以使用SFUD框架(串行Flash通用驅動庫,這部分RT-Thread已完成官方框架的移植同時提供多個應用歷程),而對上也可以使用如DFS、NVM提供的Flash硬件統一訪問接口,方便用戶更加直接方便對底層Flash硬件的訪問操作。

注:非易失性存儲器 (NVM):在芯片電源關閉期間保存存儲在其中的數據。因此,它被用于沒有磁盤的便攜式設備中的內存,以及用于可移動存儲卡等用途。主要類型有:非易失性半導體存儲器 (Non-volatile semiconductor memory, NVSM) 將數據存儲在浮柵存儲單元中,每個單元都由一個浮柵(floating-gate) MOSFET 組成。

關于存儲,可以用一張圖來解釋:

977e3c40-7f89-11ef-bb4b-92fbcf53809c.png

來源:ROMRAM、FLASH、NVM......一文搞定

1.2

使用ENV配置FAL

在RT-Thread v4.1.0之前,FAL是作為軟件包形式對用戶開放使用的,而v4.1.0之后,FAL被RT-Thread官方重新定義為RTT組件的一部分,這樣也能更加方便用戶的開發。

我們下面正式講解FAL組件的使用:

首先打開ENV工具,根據以下路徑打開FAL使能 RT-Thread Components->[*]FAL: flash abstraction layer,由于我們后面會用到SFUD,所以這里把 FAL uses SFUD drivers 一并使能,并修改FAL設備名稱為 W25Q128.

9799125e-7f89-11ef-bb4b-92fbcf53809c.png

完成上述操作后保存退出,并使用 scons --target=mdk5 重新生成MDK5文件并打開

1.3

FAL SFUD 移植

為了提供示例,我們選用W25Q128 spi flash作為測試模塊,并且使用SFUD框架對spi flash設備進行管理和驅動。

由于目前RT-Thread的SFUD已經對W25Q128完成支持,根據官方的使用手冊,我們僅需編寫fal_cfg.h文件完成對FAL_FLASH_DEV_TABLEFAL_PART_TABLE的定義即可。文件存放路徑:.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\fal_cfg.h

// fal.cfg.h
/* * 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 */#ifndef _FAL_CFG_H_#define _FAL_CFG_H_
#include #include
#ifndef FAL_USING_NOR_FLASH_DEV_NAME#define NOR_FLASH_DEV_NAME "norflash0"#else#define NOR_FLASH_DEV_NAME FAL_USING_NOR_FLASH_DEV_NAME#endif
/* Flash device Configuration */
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \{ \ &nor_flash0, \}
/* Partition Configuration */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \{ \ {FAL_PART_MAGIC_WROD, "easyflash", NOR_FLASH_DEV_NAME, 0, 512 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "download", NOR_FLASH_DEV_NAME, 512 * 1024, 1024 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "wifi_image", NOR_FLASH_DEV_NAME, (512 + 1024) * 1024, 512 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "font", NOR_FLASH_DEV_NAME, (512 + 1024 + 512) * 1024, 7 * 1024 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "filesystem", NOR_FLASH_DEV_NAME, (512 + 1024 + 512 + 7 * 1024) * 1024, 7 * 1024 * 1024, 0}, \}#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */

此時編譯的話是找不到該頭文件的,需要我們在Keil中設置:

97af01e0-7f89-11ef-bb4b-92fbcf53809c.png

在RTT FAL組件中的SFUD提供的fal_flash_dev對象默認的nor_flash0參數中,flash大小默認為8M,而W25Q128最大最16M,我們可以選擇在 .\rt-thread\components\fal\samples\porting\fal_flash_sfud_port.c文件中對struct fal_flash_dev nor_flash0 進行修改:

struct fal_flash_dev nor_flash0 ={ .name = FAL_USING_NOR_FLASH_DEV_NAME, .addr = 0, .len = 16 * 1024 * 1024, .blk_size = 4096, .ops = {init, read, write, erase}, .write_gran = 1};

當然也可以選擇不進行修改,根據大佬的原話就是因為在調用初始化接口函數init后,會從flash設備讀取正確的參數更新到nor_flash0表項中,我們在使用FAL組件前都需要調用FAL初始化函數fal_init,其內調用flash設備初始化函數fal_flash_init,最后會調用注冊到fal_flash_dev設備表項中的初始化函數device_table[i]->ops.init,所以nor_flash0表項參數會在FAL初始化時被更新。

同時我們需要開啟SFUD框架支持,打開ENV工具,由于SFUD的使用需要指定一個spi設備,這里我選擇使用最近移植好的軟件spi,路徑Hardware Drivers Config->On-chip Peripheral Drivers->[*] Enable soft SPI BUS-> [*] Enable soft SPI1 BUS (software simulation),這里我的測試開發板是恩智浦的LPC55S69-EVK,并且這款bsp的軟件模擬spi由我本人對接,關于這部分的軟件spi引腳定義可以選用默認即可,當然也可以使用自定義引腳,記住不要與其他引腳產生沖突。

97cad94c-7f89-11ef-bb4b-92fbcf53809c.png

此時我們回到ENV主界面,進入RT-Thread Components->Device Drivers->Using Serial Flash Universal Driver,此時我們才可以看到SFUD選項出現(如果沒有使能spi是沒法看到的),使能后保持默認即可

97f4d2ec-7f89-11ef-bb4b-92fbcf53809c.png

到這里,ENV的配置暫時告一段落!

1.4

FAL SFUD 測試用例

為了驗證W25Q128及軟件模擬spi在SFUD框架上是否能夠成功運行,我們在.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\下新建一個soft_spi_flash_init.c文件,代碼如下

/* * 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 #include "spi_flash.h"#include "spi_flash_sfud.h"#include "drv_soft_spi.h"#include "drv_pin.h"#include "rtconfig.h"
#define cs_pin GET_PINS(1,9)
static int rt_soft_spi_flash_init(void){ int result = -1;
result = rt_hw_softspi_device_attach("sspi1", "sspi10", cs_pin); rt_kprintf("value is %d\n",result); if(result == RT_EOK) { rt_kprintf("rt_hw_softspi_device_attach successful!\n"); }
if (RT_NULL == rt_sfud_flash_probe("W25Q128", "sspi10")) { return -RT_ERROR; }
return RT_EOK;}INIT_COMPONENT_EXPORT(rt_soft_spi_flash_init);

這里我們需要指定一個片選引腳,我暫時使用了sspi2的SCK引腳作為片選,這里注意不要同時打開sspi1sspi2,后續我會專門上傳一個通用GPIO作為片選引腳,到時候就不會產生問題了。然后軟件spi設備的掛載使用的是sspi1 bussspi10 device,并且掛載flash設備到sspi10

另外我們在.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\下新建fal_sample.c文件,并編寫測試代碼:

//fal_sample.c
/* * 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"
#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!\n"); return -1; }
partition = fal_partition_find(partiton_name); if (partition == RT_NULL) { rt_kprintf("Find partition (%s) failed!\n", 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!\n", partition->flash_name); ret = -1; return ret; }
rt_kprintf("Flash device : %s " "Flash size : %dK \n" "Partition : %s " "Partition size: %dK\n", 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!\n", partition->name); ret = -1; return ret; } rt_kprintf("Erase (%s) partition finish!\n", 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!\n", 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!\n"); 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!\n", partition->name); ret = -1; return ret; }
i += len; } rt_kprintf("Write (%s) partition finish! Write size %d(%dK).\n", 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!\n", 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!\n"); 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!\n", "font"); } else { rt_kprintf("Fal partition (%s) test failed!\n", "font"); }
if (fal_test("download") == 0) { rt_kprintf("Fal partition (%s) test success!\n", "download"); } else { rt_kprintf("Fal partition (%s) test failed!\n", "download"); }}MSH_CMD_EXPORT(fal_sample, fal sample);

1.5

測試結果

到這里就可以進行編譯下載了,成功后的截圖如下:

981720ae-7f89-11ef-bb4b-92fbcf53809c.png

2.

DFS文件系統

2.1

什么是DFS

DFS 是 RT-Thread 提供的虛擬文件系統組件,全稱為 Device File System,即設備虛擬文件系統,文件系統的名稱使用類似 UNIX 文件、文件夾的風格,目錄結構如下圖所示:

9833fba2-7f89-11ef-bb4b-92fbcf53809c.png

在 RT-Thread DFS 中,文件系統有統一的根目錄,使用 / 來表示。而在根目錄下的 f1.bin 文件則使用 /f1.bin來表示,2018 目錄下的 f1.bin 目錄則使用 /data/2018/f1.bin 來表示。即目錄的分割符號是 /,這與 UNIX/Linux 完全相同,與 Windows 則不相同(Windows 操作系統上使用 \ 來作為目錄的分割符)。

2.2

DFS架構

RT-Thread DFS 組件的主要功能特點有:

為應用程序提供統一的 POSIX 文件和目錄操作接口:read、write、poll/select 等。

支持多種類型的文件系統,如 FatFS、RomFS、DevFS 等,并提供普通文件、設備文件、網絡文件描述符的管理。

支持多種類型的存儲設備,如 SD Card、SPI Flash、Nand Flash 等。

DFS 的層次架構如下圖所示,主要分為 POSIX 接口層、虛擬文件系統層和設備抽象層。

9846c714-7f89-11ef-bb4b-92fbcf53809c.png

2.3

使用ENV配置DFS

打開ENV,進入路徑RT-Thread Components → DFS: device virtual file system,使能[*] DFS: device virtual file system

98583e7c-7f89-11ef-bb4b-92fbcf53809c.png

由于DFS使用的是POSIX接口,而dfs_posix.h已經在新版本中被移除了,如果想要兼容老版本,可以在menuconfig中使能RT-Thread Components->[*] Support legacy version for compatibility

987e9b94-7f89-11ef-bb4b-92fbcf53809c.png

由于elmfat文件系統默認最大扇區大小為512,但我們使用的flash模塊W25Q128的Flash扇區大小為4096,為了將elmfat文件系統掛載到W25Q128上,這里的Maximum sector size需要和W25Q128扇區大小保持一致,修改為4096,路徑:RT-Thread Components → DFS: device virtual file system → [*] Enable elm-chan fatfs / elm-chan's FatFs, Generic FAT Filesystem Module

9896087e-7f89-11ef-bb4b-92fbcf53809c.png

保存退出后使用scons --target=mdk5生成MDK5工程。

2.4

DFS掛載到FAL分區測試

這里增加FAL flash抽象層,我們將elmfat文件系統掛載到W25Q128 flash設備的filesystem分區上,由于FAL管理的filesystem分區不是塊設備,需要先使用FAL分區轉BLK設備接口函數將filesystem分區轉換為塊設備,然后再將DFS elmfat文件系統掛載到filesystem塊設備上。

我們接著修改fal_sample.c文件,修改后代碼:

/* * 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
#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!\n"); return -1; }
partition = fal_partition_find(partiton_name); if (partition == RT_NULL) { rt_kprintf("Find partition (%s) failed!\n", 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!\n", partition->flash_name); ret = -1; return ret; }
rt_kprintf("Flash device : %s " "Flash size : %dK \n" "Partition : %s " "Partition size: %dK\n", 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!\n", partition->name); ret = -1; return ret; } rt_kprintf("Erase (%s) partition finish!\n", 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!\n", 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!\n"); 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!\n", partition->name); ret = -1; return ret; }
i += len; } rt_kprintf("Write (%s) partition finish! Write size %d(%dK).\n", 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!\n", 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!\n"); 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!\n", "font"); } else { rt_kprintf("Fal partition (%s) test failed!\n", "font"); }
if (fal_test("download") == 0) { rt_kprintf("Fal partition (%s) test success!\n", "download"); } else { rt_kprintf("Fal partition (%s) test failed!\n", "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.\n", FS_PARTITION_NAME); else rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME);
/* make a elmfat format filesystem */ if(dfs_mkfs("elm", FS_PARTITION_NAME) == 0) rt_kprintf("make elmfat filesystem success.\n");
/* mount elmfat file system to FS_PARTITION_NAME */ if(dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0) rt_kprintf("elmfat filesystem mount success.\n");
/* Get elmfat file system statistics */ if(statfs("/", &elm_stat) == 0) rt_kprintf("elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.\n", elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree);
if(mkdir("/user", 0x777) == 0) rt_kprintf("make a directory: '/user'.\n");
rt_kprintf("Write string '%s' to /user/test.txt.\n", 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.\n");
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 \n", size, buf); }}MSH_CMD_EXPORT_ALIAS(fal_elmfat_sample, fal_elmfat,fal elmfat sample);

2.5

測試結果

測試結果如下:

98b98920-7f89-11ef-bb4b-92fbcf53809c.png

3.

Easyflash移植到FAL分區

3.1

簡述EasyFlash

關于EasyFlash的來源我們已經講過了,此處不再贅述。EasyFlash是一款開源的輕量級嵌入式Flash存儲器庫,方便開發者更加輕松的實現基于Flash存儲器的常見應用開發。非常適合智能家居、可穿戴、工控、醫療、物聯網等需要斷電存儲功能的產品,資源占用極低,支持各種 MCU 片上存儲器。

EasyFlash不僅能夠實現對產品的 設定參數運行日志信息的掉電保存功能,還封裝了簡潔的 增加、刪除、修改及查詢 方法, 降低了開發者對產品參數的處理難度,也保證了產品在后期升級時擁有更好的擴展性。讓Flash變為NoSQL(非關系型數據庫)模型的小型鍵值(Key-Value)存儲數據庫。

3.2

EasyFlash軟件包使用

打開ENV進入路徑:RT-Thread online packages → tools packages → EasyFlash: Lightweight embedded flash memory library.,選擇軟件包版本為最新版

98d0763a-7f89-11ef-bb4b-92fbcf53809c.png

配置后退出ENV,同時使用pkgs --update下載軟件包,然后再使用scons --target=mdk5重新生成MDK5文件

3.3

移植easyflash

下載完easyflash軟件包后,我們復制.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\packages\EasyFlash-latest\ports\ef_fal_port.c到目錄.\rt-thread\bsp\lpc55sxx\lpc55s69_nxp_evk\board\ports\easyflash\ef_fal_port.c,雙擊打開該文件,完成以下修改:

// 修改 FAL_EF_PART_NAME 為 easyflash#define FAL_EF_PART_NAME "easyflash"

// 修改環境變量內容為 {"boot_times", "0"},這里我們先只設置一個開機次數static const ef_env default_env_set[] = { {"boot_times", "0"},};

3.4

編寫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!\n"); return -1; }
partition = fal_partition_find(partiton_name); if (partition == RT_NULL) { rt_kprintf("Find partition (%s) failed!\n", 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!\n", partition->flash_name); ret = -1; return ret; }
rt_kprintf("Flash device : %s " "Flash size : %dK \n" "Partition : %s " "Partition size: %dK\n", 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!\n", partition->name); ret = -1; return ret; } rt_kprintf("Erase (%s) partition finish!\n", 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!\n", 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!\n"); 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!\n", partition->name); ret = -1; return ret; }
i += len; } rt_kprintf("Write (%s) partition finish! Write size %d(%dK).\n", 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!\n", 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!\n"); 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!\n", "font"); } else { rt_kprintf("Fal partition (%s) test failed!\n", "font"); }
if (fal_test("download") == 0) { rt_kprintf("Fal partition (%s) test success!\n", "download"); } else { rt_kprintf("Fal partition (%s) test failed!\n", "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.\n", FS_PARTITION_NAME); else rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME);
/* make a elmfat format filesystem */ if(dfs_mkfs("elm", FS_PARTITION_NAME) == 0) rt_kprintf("make elmfat filesystem success.\n");
/* mount elmfat file system to FS_PARTITION_NAME */ if(dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0) rt_kprintf("elmfat filesystem mount success.\n");
/* Get elmfat file system statistics */ if(statfs("/", &elm_stat) == 0) rt_kprintf("elmfat filesystem block size: %d, total blocks: %d, free blocks: %d.\n", elm_stat.f_bsize, elm_stat.f_blocks, elm_stat.f_bfree);
if(mkdir("/user", 0x777) == 0) rt_kprintf("make a directory: '/user'.\n");
rt_kprintf("Write string '%s' to /user/test.txt.\n", 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.\n");
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 \n", 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("===============================================\n"); rt_kprintf("The system now boot %d times\n", i_boot_times); rt_kprintf("===============================================\n"); /* 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);

3.5

測試結果

打開串口助手,輸入命令:

msh />easyflash_sample

第一次命令調用:

98e5ba40-7f89-11ef-bb4b-92fbcf53809c.png

第二次RESET開發板后調用:

9906c33e-7f89-11ef-bb4b-92fbcf53809c.png

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FlaSh
    +關注

    關注

    10

    文章

    1635

    瀏覽量

    148035
  • 操作系統
    +關注

    關注

    37

    文章

    6826

    瀏覽量

    123333
  • fal
    fal
    +關注

    關注

    0

    文章

    5

    瀏覽量

    6754
收藏 人收藏

    評論

    相關推薦

    FAL組件和DFS文件系統的功能特點和使用方法

    FAL (Flash Abstraction Layer)Flash 抽象層,是對 Flash 及基于 Flash 的分區進行管理、操作的抽象層,對上層統一了 Flash 及 分區操作
    的頭像 發表于 06-15 09:21 ?5258次閱讀
    <b class='flag-5'>FAL</b>組件和DFS文件系統的功能特點和使用方法

    基于FALEasyFlash移植

    MCU: STM32F072FLASH: W25Q128庫:HALSPI: SPI模式IDE: STM32CubeIDE 1.1.0裸機移植EasyFlash基于FAL(FLASH抽象層) ,FAL
    發表于 08-10 06:47

    使用fal管理spiflash,編譯的程序開機時不能正常識別并報錯

    使用fal管理spiflash,同樣的代碼,編譯后在同一臺機器上運行。后面編譯的程序,開機時可正常識別并管理flash;之前編譯的程序開機時不能正常識別,并報錯誤。后面編譯且正常的截圖:之前編譯的截圖:
    發表于 04-14 09:34

    基于RT-Thread的FAL分區該怎樣去配置呢

    日志輸出(默認開啟);分區表是否在 fal_cfg.h 中定義(默認開啟)。如果關閉此選項,fal 將會自動去指定 Flash 的指定位置去檢索并裝載分區表,具體配置詳見下面兩個選項;
    發表于 05-25 16:27

    基于rt-thread studio平臺的flash使用步驟簡析

    fal_cfg.h 中,根據需求, 調整名字和分區大小 easyfash 分區 =env+ ulog5 添加easylog 功能使用說明1 軟件包添加 ulog_easyflash
    發表于 06-02 11:35

    在RT-Thread Studio + Cubemx上如何實現對SPI FLASH的邏輯分區

    和W25Q64至此完成基本的驅動,并且驗證了板子上的SPI_FLASH狀態是正常的,那么接下來就要看看如何來實現更高級的控制。接下來使用fal軟件包,來實現對SPI_FLASH的邏輯分區,方便管理存儲空間
    發表于 06-08 15:18

    關于【easyflash 】4.0.99版本使用問題請教

    _LATEST_VERSION#define PKG_EASYFLASH_VER_NUM 0x999992、分區表配置如下:#define FAL_PART_TABLE{{
    發表于 10-28 10:07

    art-pi在rt-thread studio中添加easyflash的步驟

    ports改成port保留ef_fal_port.c編譯下載,發現沒有初始化在main函數里添加easyflash_init()。main.c可以添加#include “easyflash.h”,避免有警告
    發表于 11-07 15:09

    有沒有辦法提高easyflash讀取變量的速度呢

    硬件環境:STM32F407SPI3W25Q128軟件環境:rtthread 4.0.5easyflash 4.1.99spi3 無DMA 模式軟件配置FAL 配置:#define
    發表于 11-21 14:38

    基于Flash分區進行管理FAL Flash抽象層介紹

    1、FAL介紹FAL (Flash Abstraction Layer) Flash 抽象層,是對 Flash 及基于 Flash 的分區進行管理、操作的抽象層,對上層統一了 Flas
    發表于 11-23 15:42

    基于RT-Thread的EasyFlash移植參考示例

    備份區位于 fal 分區表中的分區名即可,默認是 "ef"。注意:在使用 fal 時,由于上面指定好了會使用整個 "ef" 分區
    發表于 11-23 15:46

    為什么使用FAL+EasyFlash往片上flash寫入數據時會出錯呢?

    問題描述:給芯片分區后往其中一塊區域內寫入默認數據時出錯版本信息RTT:V4.0.5FAL:V1.0.0EasyFlash:V4.1.0硬件信息芯片型號:AT32F407,芯片的flash為
    發表于 01-31 14:39

    怎么解決littlefs掛載第二個分區失敗的問題呢?

    首先是FAL能正常啟動,根目錄的分區也掛載正常。[D/FAL] (fal_flash_init:61) Flash device | coreboard | addr: 0x00000
    發表于 03-07 14:01

    嵌入式Linux環境變量分區制作

    嵌入式Linux環境變量分區制作嵌入式環境變量分區準備一個存放環境變量的文本文件制作環境變量的工
    發表于 11-02 10:35 ?8次下載
    嵌入式Linux環境<b class='flag-5'>變量</b><b class='flag-5'>分區</b>制作

    【LPC55S69】使用FAL分區管理easyflash變量管理(下集)

    上期帶大家了解了FAL組件和DFS文件系統的功能特點和使用方法,本期將繼續解讀如何將EasyFlsh移植到FAL分區。 簡述EasyFlash 關于
    的頭像 發表于 06-29 09:05 ?883次閱讀
    【LPC55S69】使用<b class='flag-5'>FAL</b><b class='flag-5'>分區</b><b class='flag-5'>管理</b>與<b class='flag-5'>easyflash</b><b class='flag-5'>變量</b><b class='flag-5'>管理</b>(下集)
    主站蜘蛛池模板: 黄色短视频免费看| video另类蛇交| 亚洲成a人片在线看| 1024你懂的国产精品| 中国一级特黄真人毛片| 欧美式free群乱| 午夜免费啪视频观看网站| 俄罗斯美女69xxxxxx| 色丁香六月| 午夜手机看片| 亚洲成人毛片| 免费一级欧美片在线观看| 天天干妹子| 国产精品久久久久久久久齐齐 | 欧美性黄色| 天堂在线国产| 一本大道香蕉大vr在线吗视频| 欧美成人鲁丝片在线观看| 四虎成人免费网站在线| bt天堂资源在线种子| 男人天堂黄色| 日本一区二区三区四区不卡| 新版天堂中文资源8在线| 亚洲日本在线观看| 可以直接看的黄址 | 男女交性无遮挡免费视频| 欧美xxxx色视频在线观看| 久久精品影院永久网址| 亚洲综合色吧| 97色伦人人| 日本欧美视频| 国内一国产农村妇女一级毛片| 777欧美午夜精品影院 | 免看乌克兰a一级| 国产一级大片免费看| 天堂网在线资源www最新版 | 国产成人啪午夜精品网站男同| 日韩种子| 精品精品国产高清a毛片牛牛| 无遮挡一级毛片| 天天干中文字幕|