之前尝试移植FATFS以及在cubemx上使用FATFS组件但都失败了,痛苦了两星期,最近尝试用RTthread Studio对FATFS进行移植,发现过程还是很顺利的,因此决定记录一下:
硬件:正点原子miniV3.0开发板
软件:RTthread Studio
步骤按照这里的来就可以了:
4.RT-thread 项目实战--fatfs文件系统移植_rtthread fatfs-CSDN博客
我的由于是W25q64,程序有点不一样,如下:
#include "drv_spi.h"
#include "spi_flash_sfud.h"
#include "dfs_fs.h"
#include <dfs_posix.h>
#include <BSP_w25q64.h>
static int rt_hw_spi_flash_init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
rt_hw_spi_device_attach("spi1", "spi10", GPIOA, GPIO_PIN_2);// spi10 表示挂载在 spi1总线上的 0 号设备,PA2是片选,这一步就可以将从设备挂在到总线中。
if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi10")) //注册块设备,这一步可以将外部 flash抽象为系统的块设备
{
return -RT_ERROR;
};
return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
int dfs_mount_init(void)
{
dfs_mkfs("elm","W25Q64");
if(dfs_mount("W25Q64", "/","elm",0,0) == 0) //注册块设备,这一步可以将外部flash抽象为系统的块设备
{
return -RT_ERROR;
}
return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(dfs_mount_init);
这里说一下如果打印串口报如下错误的解决方法:
Warning: Read SFDP parameter header information failed. The W25Q64 is not support JEDEC SFDP.[0m
[32m[I/SFUD] Warning: This flash device is not found or not support.[0m
[32m[I/SFUD] Error: W25Q64 flash device is initialize fail.[0m
[31m[E/SFUD] ERROR: SPI flash probe failed by SPI device spi10.[0m
这个说明RTthread的SFUD 组件在尝试初始化和识别 W25Q64 设备时遇到了问题,特别是与 JEDEC SFDP(Serial Flash Discoverable Parameters)相关的参数读取失败。这可能导致 SFUD 无法正确识别和初始化该 SPI Flash 设备。我一开始以为是W25Q64 设备不支持支持 SFDP。如果设备不支持 SFDP,就需要手动配置设备的参数,但是百度了一下是支持的,然后我就在RTthread里的cubemx中把片选引脚CS即PA2也初始化了,然后再次生成代码就可以了;(有个问题就是后面再取消cubemx的PA2初始化,生成代码后,仍然可以正常使用FATFS)
测试代码如下:
BSP_w25q64.c
// 测试文件操作
void test_file_operations(void)
{
const char *dir_path = "/Test";
// 创建并写入文件1
create_and_write_file(FILE1_PATH, "This is file 1.\n");
// 创建并写入文件2
create_and_write_file(FILE2_PATH, "This is file 2.\n");
// 读取文件1的内容
read_file_content(FILE1_PATH);
// 读取文件2的内容
read_file_content(FILE2_PATH);
//在根目录下创建一个文件夹Test
create_folder(dir_path);
// 创建并写入文件3
create_and_write_file(FILE3_PATH, "This is file 3.\n");
// 读取文件3的内容
read_file_content(FILE3_PATH);
}
// 创建并写入文件
static void create_and_write_file(const char *file_path, const char *content)
{
int fd;
int bytes_written;
// 打开文件,如果文件不存在则创建,如果文件存在则截断文件长度为0
fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC);
if (fd < 0)
{
rt_kprintf("Failed to open file for writing: %s\n", file_path);
return;
}
// 写入文件
bytes_written = write(fd, content, strlen(content));
if (bytes_written < 0)
{
rt_kprintf("Failed to write to file: %s\n", file_path);
}
else
{
rt_kprintf("Wrote %d bytes to file: %s\n", bytes_written, file_path);
}
// 关闭文件
close(fd);
}
// 读取文件内容
static void read_file_content(const char *file_path)
{
int fd;
char read_buffer[64];
int bytes_read;
// 打开文件
fd = open(file_path, O_RDONLY);
if (fd < 0)
{
rt_kprintf("Failed to open file for reading: %s\n", file_path);
return;
}
// 读取文件内容
//最多只能读sizeof(read_buffer) - 1是因为当数据超过sizeof(read_buffer) - 1大小时,read_buffer还能有一字节空间放'\0'
bytes_read = read(fd, read_buffer, sizeof(read_buffer) - 1);
if (bytes_read < 0)
{
rt_kprintf("Failed to read from file: %s\n", file_path);
}
else
{
read_buffer[bytes_read] = '\0'; // Null-terminate the string
rt_kprintf("Read %d bytes from file: %s\n", bytes_read, file_path);
rt_kprintf("File content: %s\n", read_buffer);
}
// 关闭文件
close(fd);
}
// 创建新文件夹
int create_folder(const char *folder_path)
{
if (mkdir(folder_path, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
{
rt_kprintf("Folder created successfully: %s\n", folder_path);
return 0; // 成功返回 0
}
else
{
rt_kprintf("Failed to create folder: %s\n", folder_path);
return -1; // 失败返回 -1
}
}
BSP_w25q64.h
#ifndef BSP_BSP_W25Q64_H_
#define BSP_BSP_W25Q64_H_
#define FILE1_PATH "/file1.txt"
#define FILE2_PATH "/file2.txt"
#define FILE3_PATH "/Test/file3.txt"
void test_file_operations(void);
static void create_and_write_file(const char *file_path, const char *content);
static void read_file_content(const char *file_path);
int create_folder(const char *folder_path);
#endif /* BSP_BSP_W25Q64_H_ */
测试结果如下: