[技术问答] M484 QPI之坑

[复制链接]
946|5
 楼主| apleilx 发表于 2020-4-11 15:23 | 显示全部楼层 |阅读模式
pi, spi, AD, ui, DSP
本帖最后由 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。 一般用倒可以用,但是没调到理想的效果,不知道问题出在哪里,还望知道其中奥秘的大神不吝赐。
  1. #define gd25_spi_read_delay()  NOP2()
  2. #define gd25_wait_fifo_rst()   while(GDSPI->STATUS & QSPI_STATUS_TXRXRST_Msk)

  3. /*****************************************************************************/ /*!
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]   spi data read.
  5. *****************************************************************************/
  6. uint8_t gd25_spi_read(uint8_t *datar, uint32_t Len)
  7. {
  8.     gd25_wait_fifo_rst();

  9.     if(Len&0x03)
  10.     {
  11.         while(Len--)
  12.         {
  13.             //send data
  14.             QSPI_WRITE_TX(GDSPI, 0);

  15.             //delay
  16.             gd25_spi_read_delay();

  17.             //wait for trans complete
  18.             while(QSPI_IS_BUSY(GDSPI));

  19.             //read data
  20.             *datar++ = QSPI_READ_RX(GDSPI);
  21.         }
  22.     }
  23.     else
  24.     {
  25.         uint32_t *prd32;
  26.         
  27.         //GDSPI->CTL |= QSPI_CTL_REORDER_Msk;//字节排序
  28.         QSPI_SET_DATA_WIDTH(GDSPI, 32);
  29.         
  30.         Len>>=2;
  31.         prd32 = (uint32_t *)datar;
  32.         while(Len--)
  33.         {
  34.             //send data
  35.             QSPI_WRITE_TX(GDSPI, 0);

  36.             //delay
  37.             gd25_spi_read_delay();

  38.             //wait for trans complete
  39.             while(QSPI_IS_BUSY(GDSPI));

  40.             //read data
  41.             *prd32++ = QSPI_READ_RX(GDSPI);
  42.         }

  43.         QSPI_SET_DATA_WIDTH(GDSPI, 8);
  44.         //GDSPI->CTL &= ~QSPI_CTL_REORDER_Msk; //字节排序
  45.     }
  46.    
  47.     return 0;
  48. }

  49. /*****************************************************************************/ /*!
  50. * @brief   spi data write.
  51. *****************************************************************************/
  52. uint8_t gd25_spi_cmd_send(uint8_t *dataw, uint8_t Len)
  53. {
  54.     gd25_wait_fifo_rst();

  55.     while(Len--)
  56.     {
  57.         //send data
  58.         QSPI_WRITE_TX(GDSPI, *dataw++);

  59.         //delay
  60.         gd25_spi_read_delay();

  61.         //wait for trans complete
  62.         while(QSPI_IS_BUSY(GDSPI));
  63.     }

  64.     //wait for trans complete
  65.     while(QSPI_IS_BUSY(GDSPI));

  66.     // clear RX buffer
  67.     QSPI_ClearRxFIFO(GDSPI);

  68.     return (0);
  69. }

  70. /*****************************************************************************/ /*!
  71. * @brief   read data.
  72. *****************************************************************************/
  73. uint8_t gd25_read(uint32_t addr, uint32_t Len, uint8_t *Des)
  74. {
  75.         uint8_t buff[8];

  76.         gd25_cs(0);

  77.         buff[0] = GD25CMD_Read_Data;

  78.         gd25_addr_fill(addr);

  79.         gd25_spi_cmd_send(buff, ADDR_BYTE_NUM + 1);  //cmd + addr

  80.         gd25_spi_read(Des, Len);

  81.         gd25_cs(1);

  82.         return 1;
  83. }

  84. /*****************************************************************************/ /*!
  85. * @brief   read data.
  86. *****************************************************************************/
  87. uint8_t gd25_q_read(uint32_t addr, uint32_t Len, uint8_t *Des)
  88. {
  89.         uint8_t buff[8];

  90.         gd25_cs(0);

  91.         buff[0] = GD25CMD_Quad_Read;

  92.         gd25_addr_fill(addr);

  93.         gd25_spi_cmd_send(buff, ADDR_BYTE_NUM + 2); //cmd + addr + dummy

  94.         gd25_spi_mode(GD25_QPI_READ_MODE);

  95.         gd25_qpi_read(Des, Len);

  96.         gd25_cs(1);

  97.         gd25_spi_mode(GD25_SPI_MODE);

  98.         return 1;
  99. }






antusheng 发表于 2020-4-11 22:14 | 显示全部楼层
这是要求太高了。
heisexingqisi 发表于 2020-4-12 12:37 | 显示全部楼层
速度嫌慢?
xuanhuanzi 发表于 2020-4-12 23:41 | 显示全部楼层
没用过这个功能,一般应用要求也不会这么高吧
jasontu 发表于 2020-4-13 09:02 | 显示全部楼层
看起来你的CODE是GD的。
可以先用NUVOTON官方的BSP代码作测试。
 楼主| apleilx 发表于 2020-5-1 11:35 | 显示全部楼层
jasontu 发表于 2020-4-13 09:02
看起来你的CODE是GD的。
可以先用NUVOTON官方的BSP代码作测试。

不是GD的demo,flash芯片是gd25q系列,底层函数加了gd25前缀而已,驱动代码参考是新唐的官方代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

76

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部