中级会员
 
- 积分
- 411
- 金钱
- 411
- 注册时间
- 2014-4-18
- 在线时间
- 94 小时
|
30金钱
FLASH是W25Q64,前面1M用来放其他的东西,后面7M做文件系统。一次擦写4K,现在的问题是4K以下文件读写没问题,4K以上文件写入的时候会出现数据错乱(用单片机内置的FATFS读写没问题,只有USB虚拟U盘有这个问题)。
写入之前的文件:
系统复位后再读出来后就会这样:
自己写了个程序,对比也会出现不同,但是长度没有问题,都一样长。
代码基本就是原子哥教程里的
代码:
FLASH_RESERVE_SIZE = 256
FLASH_SECTOR_SIZE = 4096
Mass_Memory_Size[0] = (4096*16*128) - (256*4096);//FLASH容量 保留1M
Mass_Block_Size[0] = 4096;//扇区大小 4K
Mass_Block_Count[0] = (128*16) - 256;//扇区个数 保留256个做升级扇区
USB读写:
[mw_shl_code=c,true]uint16_t MAL_Write(uint8_t lun, uint64_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length)
{
u8 STA;
switch (lun)
{
case EX_FLASH:
STA=0;
printf("write:%lu %u\r\n", (uint32_t)Memory_Offset, Transfer_Length);
W25Q64_Write((u8*)Writebuff, Memory_Offset + (FLASH_RESERVE_SIZE * FLASH_SECTOR_SIZE), Transfer_Length);
break;
default:
return MAL_FAIL;
}
if(STA!=0)
return MAL_FAIL;
return MAL_OK;
}[/mw_shl_code]
[mw_shl_code=applescript,true]uint16_t MAL_Read(uint8_t lun, uint64_t Memory_Offset, uint32_t *Readbuff, uint16_t Transfer_Length)
{
u8 STA;
switch (lun)
{
case EX_FLASH:
STA=0;
W25Q64_Read((u8*)Readbuff, Memory_Offset + (FLASH_RESERVE_SIZE * FLASH_SECTOR_SIZE), Transfer_Length);
break;
default:
return MAL_FAIL;
}
if(STA!=0)
return MAL_FAIL;
return MAL_OK;
}[/mw_shl_code]
底层驱动代码:
[mw_shl_code=c,true]void W25Q64_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
//初始化IO
GPIO_QuickInit(GPIOD, GPIO_Pin_8, GPIO_Mode_Out_PP); //WP
GPIO_QuickInit(GPIOB, GPIO_Pin_12, GPIO_Mode_Out_PP); //CS
GPIO_QuickInit(GPIOB, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, GPIO_Mode_AF_PP);
SPI_FLASH_CS = 1; //取消片选
//初始化SPI2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //数据大小
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行时钟的稳态:时钟悬空高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获(采样)于第二个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS软件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //波特率分频APB1外设36M/4=9M
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //MSB位在前
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
SPI_FLASH_WP = 1; //取消写保护
uint16_t spi_flash_id = W25QXX_ReadID();
if(spi_flash_id != 0XEF16)
{
while(1)
{
printf("Flash id error.It mast be 0xEF16(W25Q64). %04X\r\n",spi_flash_id);
DelayMs(1000);
}
}
}[/mw_shl_code]
[mw_shl_code=c,true]/**
* @brief SPI2读写一个字节
* @param TxData: 要写的数据
* @param *RxData: 读出的数据,如果只写的话这个给NULL
* @retval 是否成功
*/
bool SPI2_ReadWriteByte(uint8_t TxData,uint8_t *RxData)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, TxData);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
if(RxData != NULL)
*RxData = SPI_I2S_ReceiveData(SPI2);
else
SPI_I2S_ReceiveData(SPI2);
return true;
}[/mw_shl_code]
[mw_shl_code=c,true]/**
* @brief SPI2读写一个字节
* @param TxData: 要写的数据
* @param *RxData: 读出的数据,如果只写的话这个给NULL
* @retval 是否成功
*/
bool SPI2_ReadWriteByte(uint8_t TxData,uint8_t *RxData)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, TxData);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
if(RxData != NULL)
*RxData = SPI_I2S_ReceiveData(SPI2);
else
SPI_I2S_ReceiveData(SPI2);
return true;
}[/mw_shl_code]
[mw_shl_code=c,true]
/**
* @brief 写FLASH
* @param *pBuffer: 数据存储区
* @param WriteAddr: 写入地址(24bit)
* @param NumByteToWrite: 写入字节数(65535max)
* @retval None
*/
void W25Q64_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint8_t need_free = 0;
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t * W25QXX_BUF;
if(W25Q64_WRITE_BUFF == NULL)
{
W25Q64_WRITE_BUFF = m_malloc(4096);
need_free = 1;
if(W25Q64_WRITE_BUFF == NULL)
{
printf("Disk BUFF error\r\n");
return;
}
//printf("flash malloc ram\r\n");
}
W25QXX_BUF = W25Q64_WRITE_BUFF;
secpos = WriteAddr / 4096;//扇区地址
secoff = WriteAddr % 4096;//在扇区内的偏移
secremain = 4096 - secoff;//扇区剩余空间大小
if(NumByteToWrite <= secremain)
secremain = NumByteToWrite;//不大于4096个字节
while(1)
{
W25Q64_Read(W25QXX_BUF, secpos * 4096, 4096);//读出整个扇区的内容
for(i = 0; i < secremain; i++)//校验数据
{
if(W25QXX_BUF[secoff + i] != 0XFF)
break;//需要擦除
}
if(i < secremain)//需要擦除
{
W25Q64_EraseSector(secpos); //擦除这个扇区
for(i=0;i<secremain;i++) //复制
{
W25QXX_BUF[i + secoff] = pBuffer;
}
W25Q64_WriteNoCheck(W25QXX_BUF, secpos * 4096, 4096);//写入整个扇区
}
else
W25Q64_WriteNoCheck(pBuffer, WriteAddr, secremain);//写已经擦除了的,直接写入扇区剩余区间.
if(NumByteToWrite == secremain)
break;//写入结束了
else//写入未结束
{
secpos ++;//扇区地址增1
secoff = 0;//偏移位置为0
pBuffer += secremain; //指针偏移
WriteAddr += secremain; //写地址偏移
NumByteToWrite -= secremain; //字节数递减
if(NumByteToWrite > 4096)
secremain = 4096;//下一个扇区还是写不完
else
secremain = NumByteToWrite; //下一个扇区可以写完了
}
}
if(need_free)
{
m_free(W25Q64_WRITE_BUFF);
W25Q64_WRITE_BUFF = NULL;
}
}[/mw_shl_code]
|
最佳答案
查看完整内容[请看2#楼]
找到原因了,缓冲区内存不够
这里要换成Mass_Block_Size的大小
[mw_shl_code=c,true] if(Data_Buffer == NULL)
Data_Buffer = m_malloc(4096);
if(Bulk_Data_Buff == NULL)
Bulk_Data_Buff = m_malloc(4096);[/mw_shl_code]
|