我用9160开发SPI接口连接了一个W25Q64FW的外部FLASH,同步跟踪可以,发现可以读取flash ID,扇区擦除之后立即读取可以发现扇区确实擦除成功了,数据变成了0xff,但是我写入一串字符串之后,再读取出来却都是0了,看上去好像是写入失败,不知道是怎么回事,下面是我的代码:
void SPI_Flash_Init(void)
{
spi_flash = device_get_binding(FLASH_DEVICE);
if (!spi_flash)
{
printk("Could not get %s device\n", FLASH_DEVICE);
return;
}
spi_cfg.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
spi_cfg.frequency = 4000000;
spi_cfg.slave = 0;
spi_cs_ctr.gpio_dev = device_get_binding(FLASH_PORT);
if (!spi_cs_ctr.gpio_dev)
{
printk("Unable to get GPIO SPI CS device\n");
return;
}
spi_cs_ctr.gpio_pin = CS;
spi_cs_ctr.delay = 0U;
spi_cfg.cs = &spi_cs_ctr;
}
void flash_init(void)
{
gpio_flash = device_get_binding(FLASH_PORT);
if(!gpio_flash)
{
printk("Cannot bind gpio device\n");
return;
}
gpio_pin_configure(gpio_flash, CS, GPIO_DIR_OUT);
SPI_Flash_Init();
}
void SPIFlash_Erase_Sector(uint32_t SecAddr)
{
int err;
//发送写使能命令
SpiFlash_Write_Enable();
//扇区擦除命令
spi_tx_buf[0] = SPIFlash_SecErase;
//24位地址
spi_tx_buf[1] = (uint8_t)((SecAddr&0x00ff0000)>>16);
spi_tx_buf[2] = (uint8_t)((SecAddr&0x0000ff00)>>8);
spi_tx_buf[3] = (uint8_t)SecAddr;
tx_buff.buf = spi_tx_buf;
tx_buff.len = SPIFLASH_CMD_LENGTH;
tx_bufs.buffers = &tx_buff;
tx_bufs.count = 1;
err = spi_transceive(spi_flash, &spi_cfg, &tx_bufs, NULL);
if(err)
{
printk("SPI error: %d\n", err);
}
//等待W25Q128FV完成操作
SpiFlash_Wait_Busy();
}
uint16_t SpiFlash_ReadID(void)
{
int err;
uint16_t dat = 0;
//准备数据
spi_tx_buf[0] = SPIFlash_ReadID;
spi_tx_buf[1] = 0x00;
spi_tx_buf[2] = 0x00;
spi_tx_buf[3] = 0x00;
spi_tx_buf[4] = 0xFF;
spi_tx_buf[5] = 0xFF;
tx_buff.buf = spi_tx_buf;
tx_buff.len = 6;
tx_bufs.buffers = &tx_buff;
tx_bufs.count = 1;
memset(spi_rx_buf, 0, sizeof(spi_rx_buf));
rx_buff.buf = spi_rx_buf;
rx_buff.len = 6;
rx_bufs.buffers = &rx_buff;
rx_bufs.count = 1;
err = spi_transceive(spi_flash, &spi_cfg, &tx_bufs, &rx_bufs);
if(err)
{
printk("SPI error: %d\n", err);
}
else
{
printk("TX sent: %x,%x,%x,%x,%x,%x\n",
spi_tx_buf[0],
spi_tx_buf[1],
spi_tx_buf[2],
spi_tx_buf[3],
spi_tx_buf[4],
spi_tx_buf[5]
);
printk("RX recv: %x,%x,%x,%x,%x,%x\n",
spi_rx_buf[0],
spi_rx_buf[1],
spi_rx_buf[2],
spi_rx_buf[3],
spi_rx_buf[4],
spi_rx_buf[5]
);
//接收数组最后两个字节才是读取的ID
dat|=spi_rx_buf[4]<<8;
dat|=spi_rx_buf[5];
printk("flash ID: %x\n", dat);
}
return dat;
}
uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t size)
{
int err;
//检查写入的数据长度是否合法,写入长度不能超过页面的大小
if (size > (SPIFlash_PAGE_SIZE - (WriteAddr%SPIFlash_PAGE_SIZE)))
{
return false;
}
if(size == 0)
return false;
//发送写使能命令
SpiFlash_Write_Enable();
//页编程命令
spi_tx_buf[0] = SPIFlash_PageProgram;
//24位地址,高地址在前
spi_tx_buf[1] = (uint8_t)((WriteAddr&0x00ff0000)>>16);
spi_tx_buf[2] = (uint8_t)((WriteAddr&0x0000ff00)>>8);
spi_tx_buf[3] = (uint8_t)WriteAddr;
memcpy(&spi_tx_buf[4], pBuffer, size);
tx_buff.buf = spi_tx_buf;
tx_buff.len = SPIFLASH_CMD_LENGTH+size;
tx_bufs.buffers = &tx_buff;
tx_bufs.count = 1;
err = spi_transceive(spi_flash, &spi_cfg, &tx_bufs, NULL);
if(err)
{
printk("SPI error: %d\n", err);
}
}
uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t size)
{
int err;
uint8_t read_size;
spi_tx_buf[0] = SPIFlash_ReadData;
//24位地址,高地址在前
spi_tx_buf[1] = (uint8_t)((ReadAddr&0x00ff0000)>>16);
spi_tx_buf[2] = (uint8_t)((ReadAddr&0x0000ff00)>>8);
spi_tx_buf[3] = (uint8_t)ReadAddr;
tx_buff.buf = spi_tx_buf;
tx_buff.len = SPIFLASH_CMD_LENGTH;
tx_bufs.buffers = &tx_buff;
tx_bufs.count = 1;
err = spi_transceive(spi_flash, &spi_cfg, &tx_bufs, NULL);
if(err)
{
printk("SPI error: %d\n", err);
}
//开始读取数据
while(size!=0)
{
if(size<=SPI_TXRX_MAX_LEN)
{
read_size = size;
size = 0;
}
else
{
read_size = SPI_TXRX_MAX_LEN;
size -= SPI_TXRX_MAX_LEN;
}
rx_buff.buf = pBuffer;
rx_buff.len = read_size;
rx_bufs.buffers = &rx_buff;
rx_bufs.count = 1;
err = spi_transceive(spi_flash, &spi_cfg, NULL, &rx_bufs);
if(err)
{
printk("SPI error: %d\n", err);
}
pBuffer += read_size;
}
return true;
}
void test_flash(void)
{
uint16_t flash_id = 0x00;
uint16_t len = 0, i,j=1;
u8_t tmpbuf[128]={0};
flash_init();
flash_id = SpiFlash_ReadID();
sprintf(tmpbuf, "FLASH ID:%X", flash_id);
LCD_ShowString(0,60,tmpbuf);
printk("flash_id: %x\n", flash_id);
strcpy(my_tx_buf, "Hello World!");
len = strlen("Hello World!") + 1;
//写之前需要先执行擦除操作
SPIFlash_Erase_Sector(0);
SpiFlash_Read(my_rx_buf,0,len);
LCD_ShowString(0,80,"FLASH首先擦除");
//写入数据
SpiFlash_Write_Page(my_tx_buf,0,len);
LCD_ShowString(0,100,"FLASH写入数据:");
LCD_ShowString(0,120,my_tx_buf);
//读出数据
SpiFlash_Read(my_rx_buf,0,len);
LCD_ShowString(0,140,"FLASH读出数据:");
LCD_ShowString(0,160,my_rx_buf);
}