赞
踩
本文主要是在sfud的基础上进行fatfs文件系统的移植,并不对sfud的移植再进行过多的讲解了哦,所以如果想了解sfud的移植过程,请参考我的另外一篇文章:传送门
对于fatfs的介绍,野火的教程中都有详细的介绍,这里就不再赘述了。其实它的移植是比较简单的,只需要修改diskio.c文件中的相关接口函数和ffconf.h配置文件。
#include "bsp_spi.h"
#include "sfud.h"
const sfud_flash *flash1;
#define W25Q64 0xEF16 //根据板载的spiflash来修改
/* 为每个设备定义一个物理编号 */
#define ATA 0 // 预留SD卡使用
#define SPI_FLASH 1 // 外部SPI Flash
对需要修改的函数进行说明
//获取状态函数 DSTATUS disk_status(BYTE pdrv /* 物理编号 */ ) { DSTATUS status = STA_NOINIT; switch (pdrv) { case ATA: /* SD CARD */ break; case SPI_FLASH: /* SPI Flash状态检测:读取SPI Flash 设备ID */ if (W25Q64 == spi4_flash_readID()) { /* 设备ID读取结果正确 */ status &= ~STA_NOINIT; } else { /* 设备ID读取结果错误 */ status = STA_NOINIT; ; } break; default: status = STA_NOINIT; } return status; }
初始化函数
DSTATUS disk_initialize(BYTE pdrv /* 物理编号 */ ) { uint16_t i; DSTATUS status = STA_NOINIT; switch (pdrv) { case ATA: /* SD CARD */ break; case SPI_FLASH: /* SPI Flash */ sfud_init(); flash1 = sfud_get_device_table() + 0; //对应到设备表的第一个 // printf("%0x\n", spi4_flash_readID());//如果不清楚设备id的话,可以在这里打印一下 status = disk_status(SPI_FLASH); //获取设备状态 break; default: status = STA_NOINIT; } return status; }
读取函数
DRESULT disk_read(BYTE pdrv, /* 设备物理编号(0..) */ BYTE *buff, /* 数据缓存区 */ DWORD sector, /* 扇区首地址 */ UINT count /* 扇区个数(1..128) */ ) { DRESULT status = RES_PARERR; switch (pdrv) { case ATA: /* SD CARD */ break; case SPI_FLASH: //这里的左移12位,等于4096,因为flash的一个扇区是4k字节 sfud_read(flash1, sector << 12, count << 12, buff); status = RES_OK; break; default: status = RES_PARERR; } return status; }
写入函数
#if _USE_WRITE DRESULT disk_write(BYTE pdrv, /* 设备物理编号(0..) */ const BYTE *buff, /* 欲写入数据的缓存区 */ DWORD sector, /* 扇区首地址 */ UINT count /* 扇区个数(1..128) */ ) { DRESULT status = RES_PARERR; if (!count) { return RES_PARERR; /* Check parameter */ } switch (pdrv) { case ATA: /* SD CARD */ break; case SPI_FLASH: sfud_erase(flash1, sector << 12, 4096); // SPI_FLASH都是要先擦除为1才能写 sfud_write(flash1, sector << 12, count << 12, (uint8_t *)buff); status = RES_OK; break; default: status = RES_PARERR; } return status; } #endif
设备信息函数
#if _USE_IOCTL DRESULT disk_ioctl(BYTE pdrv, /* 物理编号 */ BYTE cmd, /* 控制指令 */ void *buff /* 写入或者读取数据地址指针 */ ) { DRESULT status = RES_PARERR; switch (pdrv) { case ATA: /* SD CARD */ break; case SPI_FLASH: switch (cmd) { //扇区数量就是例如我这里是8M的flash //那就是 8 * 1024 * 1024 (字节)/ 4096(一个扇区的大小) = 2048(扇区数) case GET_SECTOR_COUNT: *(DWORD *)buff = 2048; //这里是你的扇区数量 break; /* 扇区大小 */ case GET_SECTOR_SIZE: *(WORD *)buff = 4096; break; /* 同时擦除扇区个数 */ case GET_BLOCK_SIZE: *(DWORD *)buff = 1; break; } status = RES_OK; break; default: status = RES_PARERR; } return status; } #endif
获取时间函数
//这里是获取时间函数,后续如果有需要的话,可以使用rtc的时间
__weak DWORD get_fattime(void)
{
/* 返回当前时间戳 */
return ((DWORD)(2015 - 1980) << 25) /* Year 2015 */
| ((DWORD)1 << 21) /* Month 1 */
| ((DWORD)1 << 16) /* Mday 1 */
| ((DWORD)0 << 11) /* Hour 0 */
| ((DWORD)0 << 5) /* Min 0 */
| ((DWORD)0 >> 1); /* Sec 0 */
}
然后就可以开始进行测试啦
main.c文件
#include "main.h" #include "bsp_led.h" #include "bsp_usart.h" #include "gd32f4xx.h" #include "sys.h" #include "systick.h" #include <stdio.h> #include "bsp_spi.h" #include <sfud.h> #include "ff.h" FATFS fs; /* FatFs文件系统对象 */ FIL fnew; /* 文件对象 */ FRESULT res_flash; /* 文件操作结果 */ UINT fnum; /* 文件成功读写数量 */ BYTE ReadBuffer[1024]={0}; /* 读缓冲区 */ BYTE WriteBuffer[] = /* 写缓冲区*/ "欢迎使用野火STM32 F429开发板 今天是个好日子,新建文件系统测试文件\r\n"; /*! \brief main function \param[in] none \param[out] none \retval none */ int main(void) { systick_config(); led_gpio_config(); // led初始化 usart_gpio_config(115200U); /* SFUD initialize */ // if (sfud_init() == SFUD_SUCCESS) // { // sfud_demo(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf); // } printf("****** 这是一个SPI FLASH 文件系统实验 ******\r\n"); //在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化 res_flash = f_mount(&fs,"1:",1); /*----------------------- 格式化测试 ---------------------------*/ /* 如果没有文件系统就格式化创建创建文件系统 */ if(res_flash == FR_NO_FILESYSTEM) { printf("》FLASH还没有文件系统,即将进行格式化...\r\n"); /* 格式化 */ res_flash=f_mkfs("1:",0,0); if(res_flash == FR_OK) { printf("》FLASH已成功格式化文件系统。\r\n"); /* 格式化后,先取消挂载 */ res_flash = f_mount(NULL,"1:",1); /* 重新挂载 */ res_flash = f_mount(&fs,"1:",1); } else { printf("《《格式化失败。》》\r\n"); while(1); } } else if(res_flash!=FR_OK) { printf("!!外部Flash挂载文件系统失败。(%d)\r\n",res_flash); printf("!!可能原因:SPI Flash初始化不成功。\r\n"); printf("请下载 SPI—读写串行FLASH 例程测试,如果正常,在该例程f_mount语句下if语句前临时多添加一句 res_flash = FR_NO_FILESYSTEM; 让重新直接执行格式化流程\r\n"); while(1); } else { printf("》文件系统挂载成功,可以进行读写测试\r\n"); } /*----------------------- 文件系统测试:写测试 -----------------------------*/ /* 打开文件,如果文件不存在则创建它 */ printf("\r\n****** 即将进行文件写入测试... ******\r\n"); res_flash = f_open(&fnew, "1:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE ); if ( res_flash == FR_OK ) { printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n"); /* 将指定存储区内容写入到文件内 */ res_flash=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum); if(res_flash==FR_OK) { printf("》文件写入成功,写入字节数据:%d\n",fnum); printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer); } else { printf("!!文件写入失败:(%d)\n",res_flash); } /* 不再读写,关闭文件 */ f_close(&fnew); } else { printf("!!打开/创建文件失败。\r\n"); } /*------------------- 文件系统测试:读测试 ------------------------------------*/ printf("****** 即将进行文件读取测试... ******\r\n"); res_flash = f_open(&fnew, "1:FatFs读写测试文件.txt", FA_OPEN_EXISTING | FA_READ); if(res_flash == FR_OK) { printf("》打开文件成功。\r\n"); res_flash = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum); if(res_flash==FR_OK) { printf("》文件读取成功,读到字节数据:%d\r\n",fnum); printf("》读取得的文件数据为:\r\n%s \r\n", ReadBuffer); } else { printf("!!文件读取失败:(%d)\n",res_flash); } } else { printf("!!打开文件失败。\r\n"); } /* 不再读写,关闭文件 */ f_close(&fnew); /* 不再使用文件系统,取消挂载文件系统 */ f_mount(NULL,"1:",1); while (1) { } }
origin_url=image-4.png&pos_id=img-2thXHWxj-1721718767616)
相关的开源代码:gitee
如果对你有所帮助的话,请给我点一个star,嘿嘿
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。