本帖最后由 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;
- }
|