NOR Flash 是现在市场上两种主要的非易失性存储器之一。
本示例演示验证 NorFlash 的读写和擦除功能。
int flash_read (const struct device *dev, off_t offset, void *data, size_t len)
所有闪存驱动程序都支持读取,对读取偏移量、读取大小或目标地址没有对齐限制。
参数说明
字段 | 说明 |
---|---|
dev | 闪存设备 |
offset | 偏移量(字节对齐)读取 |
data | 用于存储读取数据的缓冲区 |
len | 要读取的字节数 |
成功时为 0,失败时为负 errno 代码。
int flash_write (const struct device *dev, off_t offset, const void *data, size_t len)
所有闪存驱动程序都支持位于 RAM 或 SoC 闪存中的源缓冲区,对源地址没有对齐限制。写入大小和偏移量必须是驱动程序支持的最小写入块大小的倍数。
任何必要的写保护管理均由驱动程序写入功能自执行。
参数说明
字段 | 说明 |
---|---|
dev | 闪存设备 |
offset | 写入的起始偏移量 |
data | 用于存储读取数据的缓冲区 |
len | 要读取的字节数 |
成功时为 0,失败时为负 errno 代码。
int flash_erase (const struct device *dev, off_t offset, size_t size)
可接受的擦除大小和偏移量值受特定于硬件的页面大小和偏移量倍数的影响。请检查基础子驱动程序实现的 API。
任何必要的擦除保护管理均由驱动程序擦除功能自执行。
该函数应仅用于真正显式擦除设备的设备;如果代码依赖于擦除设备,即在某些操作之前将其设置为擦除值,但应该与显式擦除和 RAM 非易失性设备一起使用,那么应该使用 flash_flatte
n。
参数说明
字段 | 说明 |
---|---|
dev | 闪存设备 |
offset | 擦除区域起始偏移量 |
size | 要擦除的区域大小 |
成功时为 0,失败时为负 errno 代码。
更多FLASH Interface Driver API接口可查看Zephyr官网FLASH Interface Driver API。
SDK 中提供了 nor_flash 的示例。
{SDK}\.sdk\csk\samples\driver\nor_flash
演示验证闪存的读写和擦除功能。
适用开发板:大模型开发套件
编译版型:csk6_duomotai_devkit
在 SDK 根目录(duomotai_ap
)下可通过执行以下指令进行对该示例工程的编译:
lisa zep build -b csk6_duomotai_devkit .sdk/csk/samples/driver/nor_flash/ -p
编译完成后,编译产物二进制文件位于 build\zephyr\zephyr.bin
使用 Type-C 数据线连接开发套件的 DAP_USB
接口,选中以下其中一种方式对固件进行烧录:
cskburn desktop
是一款聆思推出的桌面烧录工具,在下载并安装 cskburn desktop 烧录工具后,双击图标运行软件:
1.点击串口下拉框,选择连接开发套件后识别到的串口编号;
2.将编译输出的.bin
文件拖拽进烧录区域;
3.点击开始烧录,等待烧录完成。
若您已按照 《环境搭建》 教程完成开发环境的安装,可在编译完成后执行 lisa zep exec cskburn
指令完成烧录。
lisa zep exec cskburn -s \\.\COMxx -C 6 -b 1500000 0x000000 --verify-all .\build\zephyr\zephyr.bin
请将命令行中的的 COMx 替换为开发套件在 PC 上对应的串口号(可通过设备管理器查看)。例如:
COM3
。
lisa zep exec cskburn -s PORT -C 6 0x000000 --verify-all ./build/zephyr/zephyr.bin -b 1500000
请将命令行中的 PORT 替换为开发套件连接在 PC 上对应的串口号。例如:
/dev/ttyUSB0
。
烧录完成后,连接串口终端,按下开发板复位按钮,可看到串口有对应的信息输出。
以下代码与注释已省略一部分非关键接口代码,主要呈现示例的主业务流程与主要接口的使用。
CONFIG_STDOUT_CONSOLE=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_CSK6_LOCK=y
设备树文件csk6_duomotai_devkit.overlay
配置如下:
/*
* Copyright (c) 2023 Anhui(Shenzhen) Listenai Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
/delete-node/ &storage_partition;
/ {
};
&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
filesystem_part: partition@160000 {
reg = <0x160000 0x00600000>;
};
/*
* Reserve the final 640 KiB for file system partition
*/
storage_partition: partition@760000 {
reg = <0x760000 0x00a0000>;
};
};
};
1. 从设备树中获取设备的句柄
const struct device *flash_dev = DEVICE_DT_GET(DT_INST(0, listenai_csk_flash_controller));
2. 检查设备是否就绪
if (!device_is_ready(flash_dev)) {
printf("Litenai CSK6 flash driver was not found!\n");
return;
}
3. 启用闪存锁定(根据配置)
flash_lock(flash_dev);
4. 尝试写入数据并检查锁定状态
flash_write(flash_dev, FLASH_TEST_OFFSET, &test_data, sizeof(int)) != 0
5.解锁闪存并再次写入数据
flash_unlock(flash_dev);
flash_write(flash_dev, FLASH_TEST_OFFSET, &test_data, sizeof(int)) != 0
6.Test 1:擦除页并检查结果
flash_erase(flash_dev, FLASH_TEST_OFFSET, FLASH_PAGE_SIZE) != 0
7.Test 2:写入和读取数据1,验证结果
flash_write(flash_dev, offset, &buf_array_1[i], sizeof(uint32_t)) != 0
flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0
8.Test 3:擦除多页数据
flash_erase(flash_dev, offset, FLASH_PAGE_SIZE * 4) != 0
9.Test 4:写入和读取数据2,验证结果
10.Test 5:再次擦除页
11.Test 6:非字对齐写入及验证
flash_write(flash_dev, offset, &buf_array_3[i], sizeof(uint32_t)) != 0
12. 获取和打印页布局信息
rc = flash_get_page_info_by_offs(flash_dev, FLASH_TEST_OFFSET2, &info);
rc = flash_get_page_info_by_idx(flash_dev, FLASH_TEST_PAGE_IDX, &info);
13. 获取并打印写块大小
printf(" write-block-size = %u\n", flash_get_write_block_size(flash_dev));
14. 从内部闪存区域写入数据并验证
按下开发板复位按钮,可通过串口查看输出结果
int main(void)
{
const struct device *flash_dev;
uint32_t buf_array_1[4] = {TEST_DATA_WORD_0, TEST_DATA_WORD_1, TEST_DATA_WORD_2,
TEST_DATA_WORD_3};
uint32_t buf_array_2[4] = {TEST_DATA_WORD_3, TEST_DATA_WORD_1, TEST_DATA_WORD_2,
TEST_DATA_WORD_0};
uint32_t buf_array_3[8] = {TEST_DATA_WORD_0, TEST_DATA_WORD_1, TEST_DATA_WORD_2,
TEST_DATA_WORD_3, TEST_DATA_WORD_0, TEST_DATA_WORD_1,
TEST_DATA_WORD_2, TEST_DATA_WORD_3};
uint32_t buf_word = 0U;
uint32_t i, offset;
printf("\nLitenai CSK6 Flash Testing\n");
printf("=========================\n");
flash_dev = DEVICE_DT_GET(DT_INST(0, listenai_csk_flash_controller));
if (!device_is_ready(flash_dev)) {
printf("Litenai CSK6 flash driver was not found!\n");
return -1;
}