当前位置: 首页 > news >正文

基于MCU的文件系统

以后有机会就更新。

CubeMX配置

配置FATFS

驱动代码对接

user_diskio.c

修改user_diskio.c的初始化函数。因为我们的驱动芯片不需要初始化。

补充代码实现

1.读函数实现

/*** @brief  Reads Sector(s)* @param  pdrv: Physical drive number (0..)* @param  *buff: Data buffer to store read data* @param  sector: Sector address (LBA)* @param  count: Number of sectors to read (1..128)* @retval DRESULT: Operation result*/
DRESULT USER_read (BYTE pdrv,      /* Physical drive nmuber to identify the drive */BYTE *buff,     /* Data buffer to store read data */DWORD sector,   /* Sector address in LBA */UINT count      /* Number of sectors to read */
)
{/* USER CODE BEGIN READ */uint32_t i = 0;for(i=0;i<count;i++){W25QXX_Read_Sector(buff+i*4096,sector+i);}return RES_OK;/* USER CODE END READ */
}

2.写函数

/*** @brief  Writes Sector(s)* @param  pdrv: Physical drive number (0..)* @param  *buff: Data to be written* @param  sector: Sector address (LBA)* @param  count: Number of sectors to write (1..128)* @retval DRESULT: Operation result*/
#if _USE_WRITE == 1
DRESULT USER_write (BYTE pdrv,          /* Physical drive nmuber to identify the drive */const BYTE *buff,   /* Data to be written */DWORD sector,       /* Sector address in LBA */UINT count          /* Number of sectors to write */
)
{/* USER CODE BEGIN WRITE */uint32_t i = 0;for(i=0;i<count;i++){W25QXX_Write_Sector((uint8_t *)buff+i*4096,sector+i);}/* USER CODE HERE */return RES_OK;/* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */

3.IO控制函数

/*** @brief  I/O control operation* @param  pdrv: Physical drive number (0..)* @param  cmd: Control code* @param  *buff: Buffer to send/receive control data* @retval DRESULT: Operation result*/
#if _USE_IOCTL == 1
DRESULT USER_ioctl (BYTE pdrv,      /* Physical drive nmuber (0..) */BYTE cmd,       /* Control code */void *buff      /* Buffer to send/receive control data */
)
{/* USER CODE BEGIN IOCTL */DRESULT res = RES_OK;switch (cmd){case CTRL_SYNC :break;/* 扇区数量:*/case GET_SECTOR_COUNT:*(DWORD * )buff = 4096;		break;/* 扇区大小  */case GET_SECTOR_SIZE :*(WORD * )buff = 4096;break;/* 同时擦除扇区个数 */case GET_BLOCK_SIZE :*(DWORD * )buff = 1;break; case CTRL_TRIM:break;			default: res = RES_PARERR;}return res;/* USER CODE END IOCTL */
}
#endif /* _USE_IOCTL == 1 */

ffconf.h修改

将这两个宏修改为对应值。

#define _MIN_SS    512  /* 512, 1024, 2048 or 4096 */
#define _MAX_SS    4096  /* 512, 1024, 2048 or 4096 */

fatfs.c

1. MX_FATFS_Init()需要修改的地方

2. 之后在fatfs.c添加的代码

void mkfs(void)
{int res = 0;	printf("make a filesystem\r\n");res = f_mkfs("\\",1,_MAX_SS);printf("mkfs res : %d\r\n",res);
}
ZNS_CMD_EXPORT(mkfs,make a filesystem)FATFS fs;void mnt(void)
{int res = 0;	printf("mount a filesystem\r\n");res = f_mount(&fs,"\\",1);printf("mount res : %d\r\n",res);
}
ZNS_CMD_EXPORT(mnt,mount a filesystem)FIL file;void cf(int argc,char **argv)
{int res = 0;	int bwritten = 0;printf("Create file :%s\r\n",argv[1]); res = f_open(&file,argv[1],FA_WRITE | FA_CREATE_ALWAYS);printf("Create file res:%d\r\n",res); res = f_write(&file,"hello ZN!hello FS!!\r\n",21,&bwritten);printf("Write file res:%d\r\n",res); f_close(&file);}
ZNS_CMD_EXPORT(cf,open or create file)void list_directory_files(const char* path) 
{FILINFO fno;DIR dir;FRESULT res;// 打开目录res = f_opendir(&dir, path);if (res == FR_OK) {for (;;) {// 读取目录项res = f_readdir(&dir, &fno);if (res != FR_OK || fno.fname[0] == 0) break; // 结束或文件名为空// 如果是文件,打印文件名//if (!FF_FS_RPATH(&fno)) {printf("%s\r\n", fno.fname);}}f_closedir(&dir); // 关闭目录}
}void ls(void)
{printf("List All Files\r\n");	list_directory_files("\\");
}
ZNS_CMD_EXPORT(ls,list all files)uint8_t file_buf[100] = {0};void type(int argc,char **argv)
{int res = 0;	int bread=0;printf("Show File Content\r\n");	res = f_open(&file,argv[1],FA_READ);printf("Open file res : %d\r\n",res);res = f_read(&file,file_buf,30,&bread);printf("Read file res : %d\r\n",res);elog_hexdump("",16,file_buf,bread);f_close(&file);
}
ZNS_CMD_EXPORT(type,show file content)

25Q128存储芯片驱动

基于25Q128存储芯片

芯片ID的读取

底层驱动代码实现

.c文件
#include "w25q128.h"#include "stdint.h"
#include "stm32f1xx_hal.h"#include "shell.h"#include "elog.h"extern SPI_HandleTypeDef hspi2; uint8_t sector_buf[4096] = {0};/*** @brief    SPI发送指定长度的数据* @param    buf  —— 发送数据缓冲区首地址* @param    size —— 要发送数据的字节数* @retval   成功返回HAL_OK*/
static HAL_StatusTypeDef SPI_Transmit(uint8_t* send_buf, uint16_t size)
{return HAL_SPI_Transmit(&hspi2, send_buf, size, 100);
}
/*** @brief   SPI接收指定长度的数据* @param   buf  —— 接收数据缓冲区首地址* @param   size —— 要接收数据的字节数* @retval  成功返回HAL_OK*/
static HAL_StatusTypeDef SPI_Receive(uint8_t* recv_buf, uint16_t size)
{return HAL_SPI_Receive(&hspi2, recv_buf, size, 100);
}
/*** @brief   SPI在发送数据的同时接收指定长度的数据* @param   send_buf  —— 接收数据缓冲区首地址* @param   recv_buf  —— 接收数据缓冲区首地址* @param   size —— 要发送/接收数据的字节数* @retval  成功返回HAL_OK*/
static HAL_StatusTypeDef SPI_TransmitReceive(uint8_t* send_buf, uint8_t* recv_buf, uint16_t size)
{return HAL_SPI_TransmitReceive(&hspi2, send_buf, recv_buf, size, 100);
}/*等待超时时间*/
#define SPIT_FLAG_TIMEOUT         ((uint32_t)0x1000)
#define SPIT_LONG_TIMEOUT         ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))
static __IO uint32_t  SPITimeout = SPIT_LONG_TIMEOUT;   
/*** @brief  等待超时回调函数* @param  None.* @retval None.*/
static  uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{/* 等待超时后的处理,输出错误信息 */// printf("SPI 等待超时!errorCode = %d",errorCode);return 0;
}/*** @brief  使用SPI发送一个字节的数据* @param  byte:要发送的数据* @retval 返回接收到的数据*/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{SPITimeout = SPIT_FLAG_TIMEOUT;/* 等待发送缓冲区为空,TXE事件 */while (__HAL_SPI_GET_FLAG( &hspi2, SPI_FLAG_TXE ) == RESET){if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);}/* 写入数据寄存器,把要写入的数据写入发送缓冲区 */WRITE_REG(hspi2.Instance->DR, byte);SPITimeout = SPIT_FLAG_TIMEOUT;/* 等待接收缓冲区非空,RXNE事件 */while (__HAL_SPI_GET_FLAG( &hspi2, SPI_FLAG_RXNE ) == RESET){if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1);}/* 读取数据寄存器,获取接收缓冲区数据 */return READ_REG(hspi2.Instance->DR);
}//=======================================================================uint16_t W25Q128_ReadID(void)
{uint8_t send_cmd[4] = {ManufactDeviceID_CMD,0X00,0X00,0X00};uint8_t recv_data[2];SPI_FLASH_CS_LOW();SPI_Transmit(send_cmd,4);SPI_Receive(recv_data,2);return ((uint16_t *)recv_data)[0];}static uint8_t W25QXX_ReadSR()
{uint8_t result = 0; uint8_t send_buf[4] = {READ_STATU_REGISTER_1,0x00,0x00,0x00};SPI_FLASH_CS_LOW();if(HAL_OK == SPI_Transmit(send_buf, 4)) {if(HAL_OK == SPI_Receive(&result, 1)) {SPI_FLASH_CS_HIGH();return result;}}SPI_FLASH_CS_HIGH();return 0;
}static void W25QXX_Wait_Busy(void)
{while((W25QXX_ReadSR() & 0x01) == 0x01);
}void W25QXX_Write_Enable(void)
{uint8_t cmd = WRITE_ENABLE_CMD;SPI_FLASH_CS_LOW();SPI_Transmit(&cmd, 1);SPI_FLASH_CS_HIGH();W25QXX_Wait_Busy();
}void W25QXX_Erase_Sector(uint32_t sector_addr)
{   W25QXX_Write_Enable();  //擦除操作即写入0xFF,需要开启写使能W25QXX_Wait_Busy();     //等待写使能完成/* 使能片选 */SPI_FLASH_CS_LOW();/* 发送扇区擦除指令*/SPI_FLASH_SendByte(SECTOR_ERASE_CMD);/*发送擦除扇区地址的高位*/SPI_FLASH_SendByte((sector_addr & 0xFF0000) >> 16);/* 发送擦除扇区地址的中位 */SPI_FLASH_SendByte((sector_addr & 0xFF00) >> 8);/* 发送擦除扇区地址的低位 */SPI_FLASH_SendByte(sector_addr & 0xFF);/* 取消片选 */SPI_FLASH_CS_HIGH();W25QXX_Wait_Busy();       //等待扇区擦除完成
}void W25QXX_Read_Sector(uint8_t* pBuffer, uint32_t nSector)
{  uint32_t ReadAddr = nSector << 12;	W25QXX_Wait_Busy();/* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送 读 指令 */uint8_t cmd = READ_DATA_CMD;SPI_Transmit(&cmd, 1);uint8_t addr;HAL_StatusTypeDef status;/* 发送 读 地址高位 */addr = (ReadAddr & 0xFF0000) >> 16;status = SPI_Transmit(&addr, 1);/* 发送 读 地址中位 */addr = (ReadAddr& 0xFF00) >> 8;status = SPI_Transmit(&addr, 1);/* 发送 读 地址低位 */addr = ReadAddr & 0xFF;status = SPI_Transmit(&addr, 1);if(HAL_OK == status){SPI_Receive(pBuffer, 4096);}/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();
}void W25QXX_PageProgram(uint8_t* dat, uint32_t WriteAddr)
{uint8_t cmd = PAGE_PROGRAM_CMD;W25QXX_Write_Enable();/* 使能片选 */SPI_FLASH_CS_LOW();SPI_Transmit(&cmd, 1);uint8_t addr;HAL_StatusTypeDef status;/* 发送 地址高位 */addr = (WriteAddr & 0xFF0000) >> 16;status = SPI_Transmit(&addr, 1);/* 发送 地址中位 */addr = (WriteAddr & 0xFF00) >> 8;status = SPI_Transmit(&addr, 1);/* 发送 地址低位 */addr = WriteAddr & 0xFF;status = SPI_Transmit(&addr, 1);SPI_Transmit(dat, 256);/* 取消片选 */SPI_FLASH_CS_HIGH();W25QXX_Wait_Busy();
}void W25QXX_Write_Sector(uint8_t* pBuffer, uint32_t nSector)
{uint32_t WriteAddr = nSector << 12;uint32_t i = 0;	for(i=0;i<16;i++)W25QXX_PageProgram(pBuffer, WriteAddr+i*256);}void sfrd(void)
{uint16_t id = 0;	id = W25Q128_ReadID();printf("chipid = %04X\r\n",id);
}ZNS_CMD_EXPORT(sfrd,read spiflash chipid)void sfes(int argc,char **argv)
{uint32_t addr = atoi(argv[1]);printf("To erase sector No.(%d)\r\n",addr);printf("erase sector addr : %d\r\n",addr<<12);W25QXX_Erase_Sector(addr<<12);
}ZNS_CMD_EXPORT(sfes,erase sector with sector_no 0~4095)void sfrs(int argc,char **argv)
{uint32_t addr = atoi(argv[1]);printf("To read sector No.(%d)\r\n",addr);printf("read sector addr : %d\r\n",addr<<12);W25QXX_Read_Sector(sector_buf,addr<<12);elog_hexdump("",16,sector_buf,4096);
}ZNS_CMD_EXPORT(sfrs,read sector with sector_no 0~4095)void sfws(int argc,char **argv)
{uint32_t addr = atoi(argv[1]);uint32_t i = 0;printf("To write sector No.(%d)\r\n",addr);printf("write sector addr : %d\r\n",addr<<12);for(i=0;i<4096;i++) sector_buf[i] = i;W25QXX_Write_Sector(sector_buf,addr<<12);}ZNS_CMD_EXPORT(sfws,write sector with sector_no 0~4095)

.h文件
#ifndef _W25Q128_H_
#define _W25Q128_H_#include "stdint.h"#define SPI_FLASH_PageSize              256
#define SPI_FLASH_PerWritePageSize      256#define ManufactDeviceID_CMD    0x90
#define READ_STATU_REGISTER_1   0x05
#define READ_STATU_REGISTER_2   0x35
#define READ_DATA_CMD           0x03
#define WRITE_ENABLE_CMD        0x06
#define WRITE_DISABLE_CMD       0x04
#define SECTOR_ERASE_CMD        0x20
#define CHIP_ERASE_CMD          0xc7
#define PAGE_PROGRAM_CMD        0x02#define SPI_FLASH_CS_LOW()      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
#define SPI_FLASH_CS_HIGH()     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);void W25QXX_Write_Sector(uint8_t* pBuffer, uint32_t nSector);
void W25QXX_Read_Sector(uint8_t* pBuffer, uint32_t nSector);#endif

SFUD移植

http://www.dtcms.com/a/415672.html

相关文章:

  • 做网站网站代理的犯法么西安互联网公司集中在哪里
  • [吾爱原创] 带搜索的导航网站小工具,可自行添加网址
  • linux基础服务
  • C# 串口通信全解析:从基础到复杂协议的设计思路
  • 传统食品加工企业的自动化转型之路:西门子S7-200 SMART PLC助力腾飞
  • 如何做局域网网站建设国办网站建设指引
  • LinuxC++——gtest框架入门
  • 云南信息发布平台seo页面内容优化
  • 做网站英文编辑有前途吗北京招聘网站建设
  • 什么是Transformer?
  • 手机网站显示建设中鄂尔多斯 网站制作
  • wordpress制作大型网站网站建设公司86215
  • 徐州网站制作功能哪里有门户网站开发
  • 电脑行业网站模板福建省交通建设质量安全监督局网站
  • 面试官常问:NULL 对聚合函数的影响
  • 汕头模板做网站贵州省建设局八大员报名网站
  • Excel判断身份证号是否正确
  • 神经正切核(NTK):从梯度流到核方法的完整推导
  • 想在浏览器里跑 AI?TensorFlow.js 硬件支持完全指南
  • 安徽省城乡住房建设厅网站沧县官厅网站建设
  • 网站开发北京虚拟主机做网站教程
  • WSL 安装方法(简单全面)
  • 京东100道GO面试题及参考答案(上)
  • 网站被挂黑链怎么处理深圳宝安网站建设公司推荐
  • h5网站模板下载wordpress加速访问
  • 语言大模型(LLM)与自然语言处理(NLP)
  • 如何构建网站重庆中技互联
  • QML学习笔记(十五)QML的信号处理器(MouseArea)
  • php 微信 网站建设无限观影次数的app软件
  • 苏州网站建设数据网络WordPress支付宝登录