1、說明
基於SDK3.x(非3.4)移植FATFS文件系統,泰凌微提供的U盤demo工程
2、操作
A.修改drivers/8258/spi.c和spi.h
其中在spi.c中添加以下代碼(SPI驅動相關函數定義)
//MG add
void MG_spi_earse(unsigned int addr,GPIO_PinTypeDef CSPin)
{
gpio_write(CSPin,0);//CS level is low
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
reg_spi_data = 0x20;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr>>16)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr>>8)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
gpio_write(CSPin,1);//CS level is high
}
void MG_spi_Write_Enable(GPIO_PinTypeDef CSPin)
{
unsigned char cmd = 0x06;
gpio_write(CSPin,0);//CS level is low
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
reg_spi_data = cmd;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
gpio_write(CSPin,1);//CS level is high
}
void MG_spi_Standly(GPIO_PinTypeDef CSPin)
{
unsigned char cmd = 0xAB;
gpio_write(CSPin,0);//CS level is low
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
reg_spi_data = cmd;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
gpio_write(CSPin,1);//CS level is high
}
void MG_spi_write(unsigned int addr, unsigned char*buf, unsigned char len,GPIO_PinTypeDef CSPin)
{
unsigned char cmd = 0x02;
unsigned char i=0;
//MG_spi_Write_Enable(GPIO_PD6);
gpio_write(CSPin,0);//CS level is low
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
reg_spi_data = cmd;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr>>16)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr>>8)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
for(i=0; i<len ;i++)
{
reg_spi_data = buf[i];
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
}
gpio_write(CSPin,1);//CS level is high
}
void MG_spi_read(unsigned int addr, unsigned char*buf, unsigned char len,GPIO_PinTypeDef CSPin)
{
unsigned char cmd = 0x03;
unsigned char i=0;
unsigned char temp;
//MG_spi_Write_Enable(GPIO_PD6);
gpio_write(CSPin,0);//CS level is low
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
reg_spi_data = cmd;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr>>16)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr>>8)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_data = (addr)&0xFF;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
reg_spi_ctrl |=FLD_SPI_DATA_OUT_DIS;
// /***when the read_bit was set 1,you can read 0x800008 to take eight clock cycle***/
reg_spi_ctrl |= FLD_SPI_RD; //enable read,0x09-bit3 : 0 for read ,1 for write
temp = reg_spi_data; //first byte isn't useful data,only take 8 clock cycle
while(reg_spi_ctrl &FLD_SPI_BUSY ); //wait reading finished
for(i=0; i<len ;i++)
{
buf[i] = reg_spi_data;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
}
gpio_write(CSPin,1);//CS level is high
}
void MG_spi_readID(unsigned char *buf,GPIO_PinTypeDef CSPin)
{
unsigned char cmd[4] = {0x90,0x00,0x00,0x00};
unsigned char i = 0;
unsigned char temp;
gpio_write(CSPin,0);//CS level is low
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
for(i=0; i<4; i++)
{
reg_spi_data = cmd[i];
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
}
reg_spi_ctrl |=FLD_SPI_DATA_OUT_DIS;
/***when the read_bit was set 1,you can read 0x800008 to take eight clock cycle***/
reg_spi_ctrl |= FLD_SPI_RD; //enable read,0x09-bit3 : 0 for read ,1 for write
temp = reg_spi_data; //first byte isn't useful data,only take 8 clock cycle
while(reg_spi_ctrl &FLD_SPI_BUSY ); //wait reading finished
for(i=0; i<2 ;i++)
{
buf[i] = reg_spi_data;
while(reg_spi_ctrl &FLD_SPI_BUSY ); //wait reading finished
}
gpio_write(CSPin,1);//CS level is high
}
void MG_spi_write_byte(unsigned char byte)
{
reg_spi_ctrl &= ~FLD_SPI_DATA_OUT_DIS; //0x09- bit2 enables spi data output
reg_spi_ctrl &= ~FLD_SPI_RD; //enable write,0x09-bit3 : 0 for read ,1 for write
reg_spi_data = byte;
while(reg_spi_ctrl& FLD_SPI_BUSY); //wait writing finished
}
void MG_spi_write_nbyte(unsigned char *buf, unsigned short int len)
{
unsigned short int i = 0 ;
for(i=0; i<len; i++)
{
MG_spi_write_byte(*buf++);
}
}
unsigned char MG_spi_read_byte()
{
unsigned char dat = 0;
reg_spi_ctrl |=FLD_SPI_DATA_OUT_DIS;
reg_spi_ctrl |= FLD_SPI_RD;
dat = reg_spi_data; //take 8 clock cycles
while(reg_spi_ctrl & FLD_SPI_BUSY ); //wait reading finished
return dat;
}
void MG_spi_read_nbyte(unsigned char *buf, unsigned int len)
{
unsigned int i = 0;
unsigned char temp;
temp = MG_spi_read_byte();
for(i=0; i<len; i++)
{
*buf++ = MG_spi_read_byte();
}
}
在spi.h中添加以下代碼(SPI驅動相關函數聲明)
//MG add
extern void MG_spi_earse(unsigned int addr,GPIO_PinTypeDef CSPin);
extern void MG_spi_Write_Enable(GPIO_PinTypeDef CSPin);
extern void MG_spi_Standly(GPIO_PinTypeDef CSPin);
extern void MG_spi_write(unsigned int addr, unsigned char*buf, unsigned char len,GPIO_PinTypeDef CSPin);
extern void MG_spi_read(unsigned int addr, unsigned char*buf, unsigned char len,GPIO_PinTypeDef CSPin);
extern void MG_spi_readID(unsigned char *buf,GPIO_PinTypeDef CSPin);
void MG_spi_write_nbyte(unsigned char *buf, unsigned short int len);
extern void MG_spi_read_nbyte(unsigned char *buf, unsigned int len);
#define MG_SPI_CS_LOW(CSPin) gpio_write(CSPin,0)
#define MG_SPI_CS_HIGH(CSPin) gpio_write(CSPin,1)
B.在8258_USB_Disk_Demo中新建MG_SPI_Flash.c和MG_SPI_Flash.h
其中在MG_SPI_Flash.c中添加以下代碼(W25Q16U驅動相關函數定義)
#include "MG_SPI_Flash.h"
/*************************
Flash parameter define
*************************/
//Device id
#define W25Q16_MAN_ID 0x85
#define W25Q16_DEV_ID 0x14
/* Flash instruction list define */
#define W25Q16_WRTIEENABLE 0x06
#define W25Q16_WRTIEDISENABLE 0x04
#define W25Q16_READSTATUSREG 0x05
#define W25Q16_WRITESTATUSREG 0x01
#define W25Q16_READDATA 0x03
#define W25Q16_FASTREADDATA 0x0B
#define W25Q16_FASTREADDUAL 0x3B
#define W25Q16_PAGEPROGRAM 0x02
#define W25Q16_BLOCKERASE 0xD8
#define W25Q16_SECTORERASE 0x20
#define W25Q16_CHIPERASE 0xC7
#define W25Q16_POWERDOWN 0xB9
#define W25Q16_RELEASEPOWERDOWN 0xAB
#define W25Q16_DEVICEID 0xAB
#define W25Q16_MANUFACTDEVICEID 0x90
#define W25Q16_JEDECDEVICEID 0x9F
#define W25Q16_BUSY_BIT 0x01//確認Flash是否處於忙狀態Bit位
#define W25Q16_SECTORSIZE 4096
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_ReadID()
*【輸入參數】: 無
*【輸出參數】: false:ID驗證失敗
true:ID驗證成功
*【功 能】: 驗證W25Q16 device ID
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_ReadID()
{
unsigned char ReadIdCmd[4] = {0x90,0x00,0x00,0x00};
unsigned char rxbuf[2];
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(ReadIdCmd,4);
MG_spi_read_nbyte(rxbuf,2);
MG_SPI_CS_HIGH(MG_CS_PIN);
if(rxbuf[0] == W25Q16_MAN_ID ||
rxbuf[1] == W25Q16_DEV_ID )
{
//printf("data is : %d %d\r\n",rxbuf[0],rxbuf[1]);
return true;
}
return false;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_ReadSR()
*【輸入參數】: 無
*【輸出參數】: status:W25Q16當前狀態寄存器的值
*【功 能】: 讀取W25Q16狀態寄存器
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
static unsigned char Megain_SPIFlash_ReadSR()
{
unsigned char status[1] = {0};
unsigned char ReadSR_Cmd[1] = {W25Q16_READSTATUSREG};
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(ReadSR_Cmd,1);
MG_spi_read_nbyte(status,1);
MG_SPI_CS_HIGH(MG_CS_PIN);
return status[0];
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_WaitBusy()
*【輸入參數】: 無
*【輸出參數】: 無
*【功 能】: 等待W25Q16忙
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
static void Megain_SPIFlash_WaitBusy()
{
while((Megain_SPIFlash_ReadSR()&0x01));
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_WaitReady()
*【輸入參數】: 無
*【輸出參數】: 0:Flash芯片已經Ready
*【功 能】: 等待W25Q16空閒
*【作 者】: 黃金旭
*【修改時間】:2018.12.08
*******************************************************************************/
static int Megain_SPIFlash_WaitReady()
{
unsigned char status;
while(1)
{
status = Megain_SPIFlash_ReadSR();
if(!(status & W25Q16_BUSY_BIT)) //Ready
{
break;
}
}
return 0;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_WriteEnable()
*【輸入參數】: 無
*【輸出參數】: true:已經開啓寫使能
false:未成功開啓寫使能
*【功 能】: W25Q16寫使能
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
static bool Megain_SPIFlash_WriteEnable()
{
unsigned char WtiteEnable_Cmd = W25Q16_WRTIEENABLE;
unsigned char status = 0;
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(&WtiteEnable_Cmd,1);
MG_SPI_CS_HIGH(MG_CS_PIN);
status = Megain_SPIFlash_ReadSR();
if(status&0x02)
{
return true;
}
return false;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_Write(uint32_t address, uint8_t len, uint8_t *buf)
*【輸入參數】: 無
*【輸出參數】: true:開啓寫使能,且SR寄存器不爲忙
false:未成功開啓寫使能
*【功 能】: W25Q16寫操作
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_Write(unsigned int address, unsigned char len, unsigned char *buf)
{
unsigned char wbuf[4];
bool status = false;
//Megain_SPIFlash_ReleasePowerDown();
delay_us(100);
while(len>0)
{
Megain_SPIFlash_WaitReady();
status = Megain_SPIFlash_WriteEnable();
if(status == false)
{
return false;
}
unsigned int ilen;
ilen = 256 - (address % 256);
if (len < ilen)
{
ilen = len;
}
wbuf[0] = W25Q16_PAGEPROGRAM;
wbuf[1] = (address >> 16);
wbuf[2] = (address >> 8);
wbuf[3] = (address)&0xff;
address += ilen;
len -= ilen;
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(wbuf,sizeof(wbuf));
MG_spi_write_nbyte(buf,ilen);
MG_SPI_CS_HIGH(MG_CS_PIN);
Megain_SPIFlash_WaitBusy();
buf += ilen;
}
//Megain_SPIFlash_PowerDown();
return true;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_Read(uint32_t address, uint8_t len, uint8_t *buf)
*【輸入參數】: 無
*【輸出參數】: true:開啓寫使能,且SR寄存器不爲忙
false:未成功開啓寫使能
*【功 能】: W25Q16頁編程
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_Read(unsigned int address, unsigned int len, unsigned char *buf)
{
unsigned char wbuf[4];
wbuf[0] = W25Q16_READDATA;
wbuf[1] = (address>>16);
wbuf[2] = (address>>8);
wbuf[3] = (address)&0xFF;
//Megain_SPIFlash_ReleasePowerDown();
//Megain_SPIFlash_WaitReady();
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(wbuf,sizeof(wbuf));
MG_spi_read_nbyte(buf,len);
MG_SPI_CS_HIGH(MG_CS_PIN);
// if(!Megain_SPIFlash_WaitReady())
// {
// return true;
// }
//Megain_SPIFlash_PowerDown();
// return false;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_EraseChip()
*【輸入參數】: 無
*【輸出參數】: 無
*【功 能】: W25Q16片擦
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
void Megain_SPIFlash_EraseChip()
{
unsigned char wbuf[1];
wbuf[0] = W25Q16_CHIPERASE;
Megain_SPIFlash_WriteEnable();
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(wbuf,sizeof(wbuf));
MG_SPI_CS_HIGH(MG_CS_PIN);
Megain_SPIFlash_WaitBusy();
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_EraseSector(uint32_t address)
*【輸入參數】: 無
*【輸出參數】: 無
*【功 能】: W25Q16扇區擦(4K)
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
bool Megain_SPIFlash_EraseSector(unsigned int address, unsigned int len)
{
unsigned char wbuf[4];
bool status = false;
wbuf[0] = W25Q16_SECTORERASE;
wbuf[1] = (address>>16);
wbuf[2] = (address>>8);
wbuf[3] = (address)&0xFF;
status = Megain_SPIFlash_WriteEnable();
if(status == false)
{
return false;
}
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(wbuf,sizeof(wbuf));
MG_SPI_CS_HIGH(MG_CS_PIN);
Megain_SPIFlash_WaitBusy();
return true;
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_PowerDown()
*【輸入參數】: 無
*【輸出參數】: 無
*【功 能】: W25Q16 Power down模式
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
void Megain_SPIFlash_PowerDown()
{
unsigned char wbuf[1];
wbuf[0] = W25Q16_POWERDOWN;
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(wbuf,sizeof(wbuf));
MG_SPI_CS_HIGH(MG_CS_PIN);
delay_us(10);
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_ReleasePowerDown()
*【輸入參數】: 無
*【輸出參數】: 無
*【功 能】: W25Q16 解除Power down模式
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
void Megain_SPIFlash_ReleasePowerDown()
{
unsigned char wbuf[1];
wbuf[0] = W25Q16_RELEASEPOWERDOWN;
MG_SPI_CS_LOW(MG_CS_PIN);
MG_spi_write_nbyte(wbuf,sizeof(wbuf));
MG_SPI_CS_HIGH(MG_CS_PIN);
delay_us(10);
}
/*******************************************************************************
*【函數名稱】: Megain_SPIFlash_Init()
*【輸入參數】: 無
*【輸出參數】: 無
*【功 能】: SPI 初始化
*【作 者】: 黃金旭
*【修改時間】:2018.12.03
*******************************************************************************/
unsigned char Megain_SPIFlash_Init()
{
unsigned char rx_data[2] = {0,0};
unsigned char tx_data[2] = {0x02,0x06};
/*
* SDO SDI SCK CN
* A2 A3 A4 D6
* B7 B6 D7 D2
*/
spi_master_set_pin(0);//
spi_master_set_cs_pin(GPIO_PD6);
spi_master_init(3,0);//4M、mode 0
//Megain_SPIFlash_EraseChip();
//Megain_SPIFlash_ReadID();
//Megain_SPIFlash_EraseSector(0x00002000,4096);
//Megain_SPIFlash_Read(0x00002000,2,rx_data);
//printf("data is : %d %d\r\n",rx_data[0],rx_data[1]);
//Megain_SPI_Flash_Write_NoCheck(0x00002000,2,tx_data);
//Megain_SPIFlash_Write(0x00002000,2,tx_data);
//Megain_SPIFlash_Read(0x00002000,2,rx_data);
//Megain_SPIFlash_EraseSector(0x00002000,4096);
//printf("data is : %d %d\r\n",rx_data[0],rx_data[1]);
//Megain_SPIFlash_Read(0x00002000,2,rx_data);
//printf("data is : %d %d\r\n",rx_data[0],rx_data[1]);
//if(rx_data[0] == tx_data[0] && rx_data[1] == tx_data[1])
//{
return 0;
//}
//else
//{
// return 1;
//}
}
//SPI在一頁(0~65535)內寫入少於256個字節的數據
//在指定地址開始寫入最大256字節的數據
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大256),該數不應該超過該頁的剩餘字節數!!!
void Megain_SPI_Flash_Write_Page(unsigned int address ,unsigned short int len, unsigned char *buf)
{
unsigned char wbuf[4];
//Megain_SPIFlash_ReleasePowerDown();
Megain_SPIFlash_WriteEnable();
MG_SPI_CS_LOW(MG_CS_PIN);
wbuf[0] = W25Q16_PAGEPROGRAM;
wbuf[1] = (address >> 16);
wbuf[2] = (address >> 8);
wbuf[3] = (address)&0xff;
MG_spi_write_nbyte(wbuf,4);
MG_spi_write_nbyte(buf,len);
MG_SPI_CS_HIGH(MG_CS_PIN);
Megain_SPIFlash_WaitBusy();
}
//無檢驗寫SPI FLASH
//必須確保所寫的地址範圍內的數據全部爲0XFF,否則在非0XFF處寫入的數據將失敗!
//具有自動換頁功能
//在指定地址開始寫入指定長度的數據,但是要確保地址不越界!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)
//CHECK OK
//void Megain_SPI_Flash_Write_NoCheck(unsigned int address, unsigned short int len, unsigned char *buf)
//{
// unsigned short int pageremain;
// pageremain=256-address%256; //單頁剩餘的字節數
// if(len<=pageremain)
// {
// pageremain=len;//不大於256個字節
// }
// while(1)
// {
// Megain_SPI_Flash_Write_Page(address,pageremain,buf);
// if(len==pageremain)
// {
// buf=0;
// break;//寫入結束了
// }
// else //NumByteToWrite>pageremain
// {
// buf = buf + pageremain;
// address = address + pageremain; //數據地址偏移
//
// len = len - pageremain; //減去已經寫入了的字節數
// if(len>128)
// {
// pageremain=128; //一次可以寫入256個字節
// }
// else
// {
// pageremain=len; //不夠256個字節了
// }
// }
// }
//}
void Megain_SPI_Flash_Write_NoCheck(unsigned int address, unsigned short int len, unsigned char *buf)
{
unsigned short int pageremain;
pageremain=256-address%256; //單頁剩餘的字節數
if(len<=pageremain)
{
pageremain=len;//不大於256個字節
}
while(1)
{
Megain_SPI_Flash_Write_Page(address,pageremain,buf);
if(len==pageremain)
{
buf=0;
break;//寫入結束了
}
else //NumByteToWrite>pageremain
{
buf = buf + pageremain;
address = address + pageremain; //數據地址偏移
len = len - pageremain; //減去已經寫入了的字節數
if(len>128)
{
pageremain=128; //一次可以寫入256個字節
}
else
{
pageremain=len; //不夠256個字節了
}
}
}
}
//寫SPI FLASH
//在指定地址開始寫入指定長度的數據
//該函數帶擦除操作!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)
unsigned char W25Q16_BUFFER[4096];
void W25Q16_Write(unsigned char *pBuffer,unsigned int WriteAddr,unsigned short int NumByteToWrite)
{
unsigned int secpos;
unsigned short int secoff;
unsigned short int secremain;
unsigned short int i;
unsigned char *W25Q16_BUF;
W25Q16_BUF=W25Q16_BUFFER;
secpos=WriteAddr/4096;//扇區地址
secoff=WriteAddr%4096;//在扇區內的偏移
secremain=4096-secoff;//扇區剩餘空間大小
//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//測試用
if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大於4096個字節
while(1)
{
Megain_SPIFlash_Read(secpos*4096,4096,W25Q16_BUF);
//W25QXX_Read(W25Q16_BUF,secpos*4096,4096);//讀出整個扇區的內容
for(i=0;i<secremain;i++)//校驗數據
{
if(W25Q16_BUF[secoff+i]!=0XFF)break;//需要擦除
}
if(i<secremain)//需要擦除
{
Megain_SPIFlash_EraseSector(secpos,4096);//擦除這個扇區
for(i=0;i<secremain;i++) //複製
{
W25Q16_BUF[i+secoff]=pBuffer[i];
}
//W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//寫入整個扇區
Megain_SPI_Flash_Write_NoCheck(secpos*4096,4096,W25Q16_BUF);
}else Megain_SPI_Flash_Write_NoCheck(WriteAddr,secremain,pBuffer);//寫已經擦除了的,直接寫入扇區剩餘區間.
if(NumByteToWrite==secremain)break;//寫入結束了
else//寫入未結束
{
secpos++;//扇區地址增1
secoff=0;//偏移位置爲0
pBuffer+=secremain; //指針偏移
WriteAddr+=secremain;//寫地址偏移
NumByteToWrite-=secremain; //字節數遞減
if(NumByteToWrite>4096)secremain=4096; //下一個扇區還是寫不完
else secremain=NumByteToWrite; //下一個扇區可以寫完了
}
};
}
在MG_SPI_Flash.h中添加以下代碼(W25Q16U驅動相關函數聲明)
#ifndef _MG_SPI_FLASH_H
#define _MG_SPI_FLASH_H
#include "app_config.h"
//CS 引腳定義
#define MG_CS_PIN GPIO_PD6
extern bool Megain_SPIFlash_ReadID();
extern void Megain_SPIFlash_ReleasePowerDown();
extern void Megain_SPIFlash_PowerDown();
extern bool Megain_SPIFlash_EraseSector(unsigned int address, unsigned int len);
extern void Megain_SPIFlash_EraseChip();
extern bool Megain_SPIFlash_Read(unsigned int address, unsigned int len, unsigned char *buf);
extern bool Megain_SPIFlash_Write(unsigned int address, unsigned char len, unsigned char *buf);
extern unsigned char Megain_SPIFlash_Init();
extern void W25Q16_Write(unsigned char* pBuffer,unsigned int WriteAddr,unsigned short int NumByteToWrite);
extern void Megain_SPI_Flash_Write_NoCheck(unsigned int address, unsigned short int len, unsigned char *buf);
extern void Megain_SPI_Flash_Write_Page(unsigned int address ,unsigned short int len, unsigned char *buf);
#endif
C.在app.c中的user_init函數中添加以下代碼(測試W25Q16U)
unsigned char work_buf[4096];
for(i = 0; i<4096 ;i++)
{
work_buf[i] = 0xA0;
}
for(i = 0; i<4096 ;i++)
{
printf("data[%d] is :%d\r\n",i,work_buf[i]);
}
Megain_SPIFlash_Init();
Megain_SPIFlash_EraseSector(0x00001000,4096);
W25Q16_Write(work_buf,0x00001000,4096);
for(i = 0; i<4096 ;i++)
{
work_buf[i] = 0;
}
Megain_SPIFlash_Read(0x00001000,4096,work_buf);
for(i = 0; i<4096 ;i++)
{
printf("data[%d] is :%d\r\n",i,work_buf[i]);
}
3、現象
燒錄至板子後,串口成功打印出寫入W25Q16U的數據