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