Littlefs移植,FLASH用的是W25Q32

编写SPI FALSH的读写擦除函数

/**
* @brief  W25Qxx 擦除整个扇区
  * @retval uint32_t First_Addr : 第几块
  */
int32_t W25Qxx_SPI_EraseSector(uint32_t addrNb)   
{    
    addrNb*=4096;
	uint8_t CommandArray[4] = {0};
	int32_t res;
	
	CommandArray[0] = 0x20; //擦除扇区指令 命令为0x20,在手册的21页 
	CommandArray[1]	= First_Addr>>16;
	CommandArray[2]	= First_Addr>>8;
	CommandArray[3]	= First_Addr;//地址
    res = W25Qxx_SPI_TransmitOneBaye(0x06); //write enable 命令为0x06,在手册的21页  
	if(!res)
	{
		W25Qxx_SPI_WaitBusy();   
		W25Qxx_SPI_CS_LOW();	
		res = HAL_SPI_Transmit(&w25qxx_spi,CommandArray,4,10);	
		W25Qxx_SPI_CS_HIGH();  	
		W25Qxx_SPI_WaitBusy();
		W25Qxx_SPI_TransmitOneBaye(0x04);//write disenable 命令为0x06,在手册的21页  
	}                            
    return res;    				                
} 
/**
  * @brief  使用DMA读取 W25Qxx 中的数据
  * @retval uint32_t addr : 数据地址
			uint8_t  *readBuf : 读取数据的存储地址
			uint16_t size : 读取数据的存储地址
  */
int32_t W25Qxx_SPI_ReadData(uint32_t addr,uint8_t *readBuf,uint16_t size) 
{
	int32_t res;
	uint8_t CommandArray[4]; 
	CommandArray[0] = 0x03; //读指令 命令为0x20,在手册的21页 
	CommandArray[1]	= addr>>16;
	CommandArray[2]	= addr>>8;
	CommandArray[3]	= addr;//地址
	
	W25Qxx_SPI_CS_LOW();
	res = HAL_SPI_Transmit(&w25qxx_spi,CommandArray,4,10);
	if(!res)
	{
		res = HAL_SPI_Receive_DMA(&w25qxx_spi,readBuf,size);
		
		if(res)							//如果失败,关闭片选引脚
			W25Qxx_SPI_CS_HIGH();  
		else		
			W25Qxx_SPI_WaitDMARx();
	}
	else
		W25Qxx_SPI_CS_HIGH();  		
	return res;
}
/**
  * @brief  使用DMA写 W25Qxx 的数据
  * @retval uint32_t addr : 数据地址
			uint8_t  *pxData : 写数据的存储地址
			uint16_t size : 读取数据的存储地址
  */
int32_t W25Qxx_SPI_WriteData(uint32_t addr,uint8_t *pxData,uint16_t size)
{  
	int32_t res;
	uint8_t CommandArray[4]; 
	CommandArray[0] = 0x02; //写指令 命令为0x20,在手册的21页 
	CommandArray[1]	= addr>>16;
	CommandArray[2]	= addr>>8;
	CommandArray[3]	= addr;//地址
	
	res = W25Qxx_SPI_TransmitOneBaye(0x06); //write enable 命令为0x06,在手册的21页
	if(!res)	
	{
		W25Qxx_SPI_WaitBusy();
		W25Qxx_SPI_CS_LOW();
		res = HAL_SPI_Transmit(&w25qxx_spi,CommandArray,4,10);
		if(!res)
		{
			res = HAL_SPI_Transmit_DMA(&w25qxx_spi,pxData,size);
			if(res)
				W25Qxx_SPI_CS_HIGH();  	
		}
		else
			W25Qxx_SPI_CS_HIGH(); 
		
		W25Qxx_SPI_WaitDMATx();
		W25Qxx_SPI_WaitBusy();
		W25Qxx_SPI_TransmitOneBaye(0x04);//write disenable 命令为0x06,在手册的21页  
	}
	return res;
}

挂载Littlefs

#include "Littlefs_W25Qxx.h"
#include "W25Qxx_SPI.h"

#include "lfs.h"

#include "cmsis_os.h"

//#include "bsp_error.h"

uint16_t DviceID = 0;
int error_code = 0;

lfs_t lfs;
lfs_file_t file;

static int user_provided_block_device_read(
    const struct lfs_config *lfsc, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
{
	W25Qxx_SPI_ReadData((block * lfsc->block_size + off),(uint8_t *)buffer,size);
    return LFS_ERR_OK;
}

static int user_provided_block_device_prog(
    const struct lfs_config *lfsc, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
	W25Qxx_SPI_WriteData((block * lfsc->block_size + off),(uint8_t*)buffer,size);
    return LFS_ERR_OK;
}

static int user_provided_block_device_erase(const struct lfs_config *lfsc, lfs_block_t block)
{
	W25Qxx_SPI_EraseSector(block);
    return LFS_ERR_OK;
}
static int user_provided_block_device_sync(const struct lfs_config *lfsc)
{
    return LFS_ERR_OK;
}

static uint8_t lfs_read_cache_buf[256];
static uint8_t lfs_prog_cache_buf[256];
static uint8_t lfs_lookahead_buf[16];	// 128/8=16

char WriteBuf[] = {"Hi,Budy! if you get this Message......Congratulations!You have succeeded!!"};
char ReadBuf[80];
// configuration of the filesystem is provided by this struct
const struct lfs_config cfg = {
	// block device driver context data
	.context = NULL,
    // block device operations
    .read  = user_provided_block_device_read, //读取数据  
    .prog  = user_provided_block_device_prog, //编程一个扇区
    .erase = user_provided_block_device_erase,//擦除一个扇区
    .sync  = user_provided_block_device_sync,

    // block device configuration
    .read_size = 256,//FLASH_PAGE_SIZE 页大小,读取块的最小大小。所有读取操作都将是
    .prog_size = 256,//FLASH_PAGE_SIZE 页大小,块程序的最小大小。所有程序操作都将是
    .block_size = 4096,//FLASH_SECTOR_SIZE 扇区大小
    .block_count = 1024,//扇区数量
	.cache_size = 256,//缓存大小
	.block_cycles = 200,// 范围在100-1000之间,值越大,性能越好,但磨损分布不均匀。
	.lookahead_size = 128,//前瞻缓冲区的大小(以字节为单位)。较大的超前缓冲区会增加分配过程中找到的块数。前瞻缓冲区存储为紧凑位图,因此RAM的每个字节可以跟踪8个块。必须是8的倍数。
	.read_buffer = lfs_read_cache_buf,//长度必须是cache
	.prog_buffer = lfs_prog_cache_buf,//长度必须是cache
	.lookahead_buffer = lfs_lookahead_buf,
};

void Littlefs_Main(void *argument)
{
	W25Qxx_Init();
	
	W25Qxx_SPI_ReadDviceID(&DviceID);
	
	int err = lfs_mount(&lfs, &cfg);
	if (err) 
	{
        lfs_format(&lfs, &cfg);
        lfs_mount(&lfs, &cfg);
    }
	//写一个文件的流程
//	/*
	lfs_file_open(&lfs, &file, "my_file", LFS_O_RDWR | LFS_O_CREAT);
	lfs_file_rewind(&lfs, &file);
	lfs_file_write(&lfs, &file, &WriteBuf, sizeof(WriteBuf));
	lfs_file_close(&lfs, &file);
	lfs_unmount(&lfs);
//	*/
	//删除一个文件的流程
	/*
	error_code = lfs_remove(&lfs,"my_file");
	lfs_unmount(&lfs);
//	*/
	
	for(;;)
	{
		//读一个文件的流程
//		/*
		lfs_file_open(&lfs, &file, "my_file", LFS_O_RDWR | LFS_O_CREAT);
		lfs_file_read(&lfs, &file, &ReadBuf, sizeof(ReadBuf));
		lfs_file_close(&lfs, &file);
		lfs_unmount(&lfs);
//		*/
	
		osDelay(1000);
	}
}

做了进一步的封装

/**
  * @brief 	写一个文件
*/
void fs_write(const char *file_name,const void *buffer,uint32_t size)
{
	lfs_file_t file;
	lfs_file_open(&lfs, &file, file_name, LFS_O_RDWR | LFS_O_CREAT);
	lfs_file_rewind(&lfs, &file);
	lfs_file_write(&lfs, &file, buffer, size);
	lfs_file_close(&lfs, &file);
	lfs_unmount(&lfs);
}
/**
  * @brief 	读一个文件
*/
void fs_read(const char *file_name,void *buffer,uint32_t size)
{
	lfs_file_t file;
	lfs_file_open(&lfs, &file, file_name, LFS_O_RDWR | LFS_O_CREAT);
	lfs_file_read(&lfs, &file, buffer, size);
	lfs_file_close(&lfs, &file);
	lfs_unmount(&lfs);
}
void app_mian(void *argument)
{
	Littlefs_mount();
	fs_write("config.txt",WriteBuf,sizeof(WriteBuf));
	for(;;)
	{
		fs_read("config.txt",ReadBuf,sizeof(WriteBuf));
		osDelay(1000);
	}
}

你可能感兴趣的:(单片机,stm32,flash,spi)