本帖最后由 apleilx 于 2020-4-11 15:27 编辑
自己做了个M484挂接 SPI-NOR 和 SPI-NAND的评估板,研究下spi- falsh 操作方法。
之前有个板载spi-nor的GD32的板子只有SPI模式,SPI时钟24MHz,连续读取平均 2.4MB/s。
这次的M484,CPU主频192MHz,SPI时钟同样设为24MHz。
先用SPI模式,8bits数据位宽,无论怎么调连续读只能达到,1.1MB/s。
后来读数据时将SPI改为32bits模式,可以达到2.07MB/s,但这种情况其他配置不变,开启字节排序功能后立刻又变为1.1MB/s。十分诡异。
然后测QPI模式,一开始用8位宽,最高只能 2.1MB/s。
改用32bits位宽后,可以到4.4MB/s,同样其他配置不变,如果开启字节排序功能速度立马变为2.1MB/s。
SPI和QPI模式软件开销上只是多了两句寄存器修改,其他一样,QPI理论速度应该是SPI模式3倍以上,实际只有两倍左右,比较费解。
至此已经无能为力了,本来以为24MHz时钟QPI可以达到10MB/s以上的,结果只实现了不到一半的速度。
另外SPI-NAND 添加 lut 只调到了3.8MB/s。 一般用倒可以用,但是没调到理想的效果,不知道问题出在哪里,还望知道其中奥秘的大神不吝赐。
#define gd25_spi_read_delay() NOP2()
#define gd25_wait_fifo_rst() while(GDSPI->STATUS & QSPI_STATUS_TXRXRST_Msk)
/*****************************************************************************/ /*!
* [url=home.php?mod=space&uid=247401]@brief[/url] spi data read.
*****************************************************************************/
uint8_t gd25_spi_read(uint8_t *datar, uint32_t Len)
{
gd25_wait_fifo_rst();
if(Len&0x03)
{
while(Len--)
{
//send data
QSPI_WRITE_TX(GDSPI, 0);
//delay
gd25_spi_read_delay();
//wait for trans complete
while(QSPI_IS_BUSY(GDSPI));
//read data
*datar++ = QSPI_READ_RX(GDSPI);
}
}
else
{
uint32_t *prd32;
//GDSPI->CTL |= QSPI_CTL_REORDER_Msk;//字节排序
QSPI_SET_DATA_WIDTH(GDSPI, 32);
Len>>=2;
prd32 = (uint32_t *)datar;
while(Len--)
{
//send data
QSPI_WRITE_TX(GDSPI, 0);
//delay
gd25_spi_read_delay();
//wait for trans complete
while(QSPI_IS_BUSY(GDSPI));
//read data
*prd32++ = QSPI_READ_RX(GDSPI);
}
QSPI_SET_DATA_WIDTH(GDSPI, 8);
//GDSPI->CTL &= ~QSPI_CTL_REORDER_Msk; //字节排序
}
return 0;
}
/*****************************************************************************/ /*!
* @brief spi data write.
*****************************************************************************/
uint8_t gd25_spi_cmd_send(uint8_t *dataw, uint8_t Len)
{
gd25_wait_fifo_rst();
while(Len--)
{
//send data
QSPI_WRITE_TX(GDSPI, *dataw++);
//delay
gd25_spi_read_delay();
//wait for trans complete
while(QSPI_IS_BUSY(GDSPI));
}
//wait for trans complete
while(QSPI_IS_BUSY(GDSPI));
// clear RX buffer
QSPI_ClearRxFIFO(GDSPI);
return (0);
}
/*****************************************************************************/ /*!
* @brief read data.
*****************************************************************************/
uint8_t gd25_read(uint32_t addr, uint32_t Len, uint8_t *Des)
{
uint8_t buff[8];
gd25_cs(0);
buff[0] = GD25CMD_Read_Data;
gd25_addr_fill(addr);
gd25_spi_cmd_send(buff, ADDR_BYTE_NUM + 1); //cmd + addr
gd25_spi_read(Des, Len);
gd25_cs(1);
return 1;
}
/*****************************************************************************/ /*!
* @brief read data.
*****************************************************************************/
uint8_t gd25_q_read(uint32_t addr, uint32_t Len, uint8_t *Des)
{
uint8_t buff[8];
gd25_cs(0);
buff[0] = GD25CMD_Quad_Read;
gd25_addr_fill(addr);
gd25_spi_cmd_send(buff, ADDR_BYTE_NUM + 2); //cmd + addr + dummy
gd25_spi_mode(GD25_QPI_READ_MODE);
gd25_qpi_read(Des, Len);
gd25_cs(1);
gd25_spi_mode(GD25_SPI_MODE);
return 1;
}
|