[综合信息] 【华大测评】HC32F460测试QSPI通讯测试

[复制链接]
13690|51
 楼主| binoo7 发表于 2021-2-8 15:25 | 显示全部楼层 |阅读模式
本帖最后由 binoo7 于 2021-2-8 15:39 编辑

@小跑堂
第一期测评用了GPIO,这次我们来说说QSPI。其实前几天写过一篇原创的**就是关于QSPI的,那篇**是对华大HC32F460的简介及配置的一个说明。
今天是来做一个QSPI的实验,在做实验之前,再说一下关于华大QSPI的通讯,
首先,与其他的芯片的QSPI类似,华大的QSPI支持的通讯方式有两种,按照手册的说法,
一种叫做直接通讯,
一种叫做ROM映射,
这两个通讯方式有什么区别呢?
首先说ROM映射,这方面的**我找到的资料比较少,只能根据自己的实验过程理解和大家做一个分享,还望大家海涵。
ROM映射是把片外的flash映射到内存中,可以和读取内存类似的访问片外的flash,
在访问的时候有多种的访问方式:
•  支持多种读取方式
a.标准读/快速读
b.二线式输出快速读取/二线式输入输出快速读取
c.四线式输出快速读取/四线式输入输出快速读取
•  自由设置指令
•  数量可调的虚拟周期
•  16字节的预读取功能
•  状态查询功能
•  SPI总线周期延长功能
•  XIP控制功能
而且,相关的寄存器也比较丰富
364276020e402b999c.png
几乎是除了直接通讯指令寄存器以外的,他都可以设置了
ROM映射的好处是,读取数据是硬件自己完成的,不需要额外的在写读取的函数,这样直接访问响应的地址,就可以读取到片外的存储的数据了
如下图所示
781086020e4862bf77.png
看到红色方框内的内容了吧,这就是关键的地方,内存映射的起始地址是固定的,也就是可以访问这么多的内存空间,
在应用中这样就可以直接读取到地址中的数据了
412536020e4f574371.png
看到图片中绿色的部分了吗?读取数据真的挺方便的
写入数据不可以直接对该地址进行赋值,需要通过特定的函数进行写入的操作。
是不是感觉很神奇呢,和SPI一比是不是有很大的优势啊
写入和读取都可以通过4根数据线同时进行,这样读写的速度会大大提高说完了ROM映射的功能,下面说说直接通讯的方式。
QSPI 可以通过自动将 MCU 的外部 ROM 读取总线周期转换为 QSPI 总线周期来对串行闪存进行读取。
但串行闪存还有很多不同的追加功能,诸如 ID 信息读取,擦除,写入及状态信息读取等。
这些功能并没有一套标准的指令来进行设置,并且随着串行闪存新功能的迅速增加,硬件层面上的对应变得愈发的困难。
针对这种情况,QSPI 提供了直接通信模式,用户可通过软件直接对串行闪存进行控制。
由此模式软件可以产生任意所需的 QSPI 总线周期。

将 QSCR 寄存器的 DCOME 位设成 1 可以进入直接通信模式。一旦进入直接通信模式,将无法进行通常的闪存读取操作,
如果要进行常规的闪存读取,需要将 DCOME位清零退出直接通信模式。
注意:
- 如果处于 XIP 模式,则需要先退出 XIP 模式再启动直接通信模式。
- 在直接通信模式下是无法对 QSCR 和 QSDCOM 以外的寄存器进行写操作的。对其他寄存器
的写操作将会退出直接通信模式。


下面看一下实验的代码,方式通过的是直接内存映射的方式来做的实验

  1. #include "hc32_ddl.h"

  2. /*******************************************************************************
  3. * Local type definitions ('typedef')
  4. ******************************************************************************/

  5. /*******************************************************************************
  6. * Local pre-processor symbols/macros ('#define')
  7. ******************************************************************************/
  8. /* LED0 Port/Pin definition */
  9. #define LED0_PORT                       (PortE)
  10. #define LED0_PIN                        (Pin06)

  11. #define LED0_ON()                       (PORT_SetBits(LED0_PORT, LED0_PIN))
  12. #define LED0_OFF()                      (PORT_ResetBits(LED0_PORT, LED0_PIN))
  13. #define LED0_TOGGLE()                   (PORT_Toggle(LED0_PORT, LED0_PIN))

  14. /* LED1 Port/Pin definition */
  15. #define LED1_PORT                       (PortA)
  16. #define LED1_PIN                        (Pin07)

  17. #define LED1_ON()                       (PORT_SetBits(LED1_PORT, LED1_PIN))
  18. #define LED1_OFF()                      (PORT_ResetBits(LED1_PORT, LED1_PIN))
  19. #define LED1_TOGGLE()                   (PORT_Toggle(LED1_PORT, LED1_PIN))

  20. /* KEY0 Port/Pin definition */
  21. #define KEY0_PORT                       (PortD)
  22. #define KEY0_PIN                        (Pin03)

  23. /* QSPCK Port/Pin definition */
  24. #define QSPCK_PORT                      (PortC)
  25. #define QSPCK_PIN                       (Pin06)

  26. /* QSNSS Port/Pin definition */
  27. #define QSNSS_PORT                      (PortC)
  28. #define QSNSS_PIN                       (Pin07)

  29. /* QSIO0 Port/Pin definition */
  30. #define QSIO0_PORT                      (PortD)
  31. #define QSIO0_PIN                       (Pin08)

  32. /* QSIO1 Port/Pin definition */
  33. #define QSIO1_PORT                      (PortD)
  34. #define QSIO1_PIN                       (Pin09)

  35. /* QSIO2 Port/Pin definition */
  36. #define QSIO2_PORT                      (PortD)
  37. #define QSIO2_PIN                       (Pin10)

  38. /* QSIO3 Port/Pin definition */
  39. #define QSIO3_PORT                      (PortD)
  40. #define QSIO3_PIN                       (Pin11)

  41. /* QSPI memory bus address definition */
  42. #define QSPI_BUS_ADDRESS                (0x98000000ul)
  43. /* FLASH parameters definition */
  44. #define FLASH_PAGE_SIZE                 (0x100u)
  45. #define FLASH_SECTOR_SIZE               (0x1000u)
  46. #define FLASH_MAX_ADDR                  (0x800000ul)
  47. #define FLASH_DUMMY_BYTE_VALUE          (0xffu)
  48. #define FLASH_BUSY_BIT_MASK             (0x01u)

  49. /* FLASH instruction definition */
  50. #define FLASH_INSTR_WRITE_ENABLE        (0x06u)
  51. #define FLASH_INSTR_PAGE_PROGRAM        (0x02u)
  52. #define FLASH_INSTR_ERASE_4KB_SECTOR    (0x20u)
  53. #define FLASH_INSTR_ERASE_CHIP          (0xC7u)
  54. #define FLASH_INSTR_READ_SR1            (0x05u)
  55. #define FLASH_INSTR_READ_SR2            (0x35u)
  56. #define FLASH_INSTR_READ_SR3            (0x15u)

  57. /*******************************************************************************
  58. * Global variable definitions (declared in header file with 'extern')
  59. ******************************************************************************/

  60. /*******************************************************************************
  61. * Local function prototypes ('static')
  62. ******************************************************************************/

  63. /*******************************************************************************
  64. * Local variable definitions ('static')
  65. ******************************************************************************/
  66. static uint8_t u8ExIntFlag = 0u;

  67. /*******************************************************************************
  68. * Function implementation - global ('extern') and local ('static')
  69. ******************************************************************************/
  70. /**
  71. *******************************************************************************
  72. ** \brief ExtInt3 callback function
  73. **
  74. ** \param [in] None
  75. **
  76. ** \retval None
  77. **
  78. ******************************************************************************/
  79. void ExtInt03_Callback(void)
  80. {
  81.     if (Set == EXINT_Irq**Get(ExtiCh03))
  82.     {
  83.         u8ExIntFlag = 1u;
  84.         EXINT_Irq**Clr(ExtiCh03);
  85.     }
  86. }

  87. /**
  88. *******************************************************************************
  89. ** \brief KEY0(SW2) init function
  90. **
  91. ** \param [in] None
  92. **
  93. ** \retval None
  94. **
  95. ******************************************************************************/
  96. void Sw2_Init(void)
  97. {
  98.     stc_port_init_t stcPortInit;
  99.     stc_exint_config_t stcExtiConfig;
  100.     stc_irq_regi_conf_t stcIrqRegiConf;

  101.     /* configure structure initialization */
  102.     MEM_ZERO_STRUCT(stcPortInit);
  103.     MEM_ZERO_STRUCT(stcExtiConfig);
  104.     MEM_ZERO_STRUCT(stcIrqRegiConf);

  105.     /* Set PD03 as External Int Ch.3 input */
  106.     stcPortInit.enExInt = Enable;
  107.     PORT_Init(KEY0_PORT, KEY0_PIN, &stcPortInit);

  108.     stcExtiConfig.enExitCh = ExtiCh03;
  109.     /* Filter setting */
  110.     stcExtiConfig.enFilterEn = Enable;
  111.     stcExtiConfig.enFltClk = Pclk3Div8;
  112.     /* Both edge */
  113.     stcExtiConfig.enExtiLvl = ExIntFallingEdge;
  114.     EXINT_Init(&stcExtiConfig);

  115.     /* Select External Int Ch.3 */
  116.     stcIrqRegiConf.enIntSrc = INT_PORT_EIRQ3;
  117.     /* Register External Int to Vect.No.007 */
  118.     stcIrqRegiConf.enIRQn = Int007_IRQn;
  119.     /* Callback function */
  120.     stcIrqRegiConf.pfnCallback = &ExtInt03_Callback;
  121.     /* Registration IRQ */
  122.     enIrqRegistration(&stcIrqRegiConf);

  123.     /* Clear pending */
  124.     NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
  125.     /* Set priority */
  126.     NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_15);
  127.     /* Enable NVIC */
  128.     NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
  129. }

  130. /**
  131. *******************************************************************************
  132. ** \brief QSPI flash init function
  133. **
  134. ** \param [in] None
  135. **
  136. ** \retval None
  137. **
  138. ******************************************************************************/
  139. void QspiFlash_Init(void)
  140. {
  141.     stc_qspi_init_t stcQspiInit;

  142.     /* configuration structure initialization */
  143.     MEM_ZERO_STRUCT(stcQspiInit);

  144.     /* Configuration peripheral clock */
  145.     PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_QSPI, Enable);

  146.     /* Configuration QSPI pin */
  147.     PORT_SetFunc(QSPCK_PORT, QSPCK_PIN, Func_Qspi, Disable);
  148.     PORT_SetFunc(QSNSS_PORT, QSNSS_PIN, Func_Qspi, Disable);
  149.     PORT_SetFunc(QSIO0_PORT, QSIO0_PIN, Func_Qspi, Disable);
  150.     PORT_SetFunc(QSIO1_PORT, QSIO1_PIN, Func_Qspi, Disable);
  151.     PORT_SetFunc(QSIO2_PORT, QSIO2_PIN, Func_Qspi, Disable);
  152.     PORT_SetFunc(QSIO3_PORT, QSIO3_PIN, Func_Qspi, Disable);

  153.     /* Configuration QSPI structure */
  154.     stcQspiInit.enClkDiv = QspiHclkDiv3;
  155.     stcQspiInit.enSpiMode = QspiSpiMode3;
  156.     stcQspiInit.enBusCommMode = QspiBusModeRomAccess;
  157.     stcQspiInit.enPrefetchMode = QspiPrefetchStopComplete;
  158.     stcQspiInit.enPrefetchFuncEn = Disable;
  159.     stcQspiInit.enQssnValidExtendTime = QspiQssnValidExtendSck32;
  160.     stcQspiInit.enQssnIntervalTime = QspiQssnIntervalQsck8;
  161.     stcQspiInit.enQsckDutyCorr = QspiQsckDutyCorrHalfHclk;
  162.     stcQspiInit.enVirtualPeriod = QspiVirtualPeriodQsck6;
  163.     stcQspiInit.enWpPinLevel = QspiWpPinOutputHigh;
  164.     stcQspiInit.enQssnSetupDelayTime = QspiQssnSetupDelay1Dot5Qsck;
  165.     stcQspiInit.enQssnHoldDelayTime = QspiQssnHoldDelay1Dot5Qsck;
  166.     stcQspiInit.enFourByteAddrReadEn = Disable;
  167.     stcQspiInit.enAddrWidth = QspiAddressByteThree;
  168.     stcQspiInit.stcCommProtocol.enReadMode = QspiReadModeFourWiresIO;
  169.     stcQspiInit.stcCommProtocol.enTransInstrProtocol = QspiProtocolExtendSpi;
  170.     stcQspiInit.stcCommProtocol.enTransAddrProtocol = QspiProtocolExtendSpi;
  171.     stcQspiInit.stcCommProtocol.enReceProtocol = QspiProtocolExtendSpi;
  172.     stcQspiInit.u8RomAccessInstr = QSPI_3BINSTR_FOUR_WIRES_IO_READ;
  173.     QSPI_Init(&stcQspiInit);
  174. }

  175. /**
  176. *******************************************************************************
  177. ** \brief QSPI flash write enable function
  178. **
  179. ** \param [in] None
  180. **
  181. ** \retval None
  182. **
  183. ******************************************************************************/
  184. void QspiFlash_WriteEnable(void)
  185. {
  186.     QSPI_EnterDirectCommMode();
  187.     QSPI_WriteDirectCommValue(FLASH_INSTR_WRITE_ENABLE);
  188.     QSPI_ExitDirectCommMode();
  189. }

  190. /**
  191. *******************************************************************************
  192. ** \brief QSPI flash wait for write operation end function
  193. **
  194. ** \param [in] None
  195. **
  196. ** \retval Ok                              Flash internal operation finish
  197. ** \retval ErrorTimeout                    Flash internal operation timeout
  198. **
  199. ******************************************************************************/
  200. en_result_t QspiFlash_WaitForWriteEnd(void)
  201. {
  202.     en_result_t enRet = Ok;
  203.     uint8_t u8Status = 0u;
  204.     uint32_t u32Timeout;
  205.     stc_clk_freq_t stcClkFreq;

  206.     CLK_GetClockFreq(&stcClkFreq);
  207.     u32Timeout = stcClkFreq.sysclkFreq / 1000u;
  208.     QSPI_EnterDirectCommMode();
  209.     QSPI_WriteDirectCommValue(FLASH_INSTR_READ_SR1);
  210.     do
  211.     {
  212.         u8Status = QSPI_ReadDirectCommValue();
  213.         u32Timeout--;
  214.     } while ((u32Timeout != 0u) &&
  215.              ((u8Status & FLASH_BUSY_BIT_MASK) == FLASH_BUSY_BIT_MASK));

  216.     if (FLASH_BUSY_BIT_MASK == u8Status)
  217.     {
  218.         enRet = ErrorTimeout;
  219.     }
  220.     QSPI_ExitDirectCommMode();

  221.     return enRet;
  222. }

  223. /**
  224. *******************************************************************************
  225. ** \brief QSPI flash page write program function
  226. **
  227. ** \param [in] u32Addr                     Valid flash address
  228. **
  229. ** \param [in] pData                       Pointer to send data buffer
  230. **
  231. ** \param [in] len                         Send data length
  232. **
  233. ** \retval Error                           Page write program failed
  234. ** \retval Ok                              Page write program success
  235. **
  236. ******************************************************************************/
  237. en_result_t QspiFlash_WritePage(uint32_t u32Addr, const uint8_t pData[], uint16_t len)
  238. {
  239.     en_result_t enRet = Ok;
  240.     uint16_t u16Index = 0u;

  241.     if ((u32Addr > FLASH_MAX_ADDR) || (NULL == pData) || (len > FLASH_PAGE_SIZE))
  242.     {
  243.         enRet = Error;
  244.     }
  245.     else
  246.     {
  247.         QspiFlash_WriteEnable();
  248.         /* Send data to flash */
  249.         QSPI_EnterDirectCommMode();
  250.         QSPI_WriteDirectCommValue(FLASH_INSTR_PAGE_PROGRAM);
  251.         QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF0000ul) >> 16));
  252.         QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF00u) >> 8));
  253.         QSPI_WriteDirectCommValue((uint8_t)(u32Addr & 0xFFu));
  254.         while (len--)
  255.         {
  256.            QSPI_WriteDirectCommValue(pData[u16Index]);
  257.            u16Index++;
  258.         }
  259.         QSPI_ExitDirectCommMode();
  260.         /* Wait for flash idle */
  261.         enRet = QspiFlash_WaitForWriteEnd();
  262.     }

  263.     return enRet;
  264. }

  265. /**
  266. *******************************************************************************
  267. ** \brief QSPI flash erase 4Kb sector function
  268. **
  269. ** \param [in] u32Addr                     Valid flash address
  270. **
  271. ** \retval Error                           Sector erase failed
  272. ** \retval Ok                              Sector erase success
  273. **
  274. ******************************************************************************/
  275. en_result_t QspiFlash_Erase4KbSector(uint32_t u32Addr)
  276. {
  277.     en_result_t enRet = Ok;

  278.     if (u32Addr >= FLASH_MAX_ADDR)
  279.     {
  280.         enRet = Error;
  281.     }
  282.     else
  283.     {
  284.         QspiFlash_WriteEnable();
  285.         /* Send instruction to flash */
  286.         QSPI_EnterDirectCommMode();
  287.         QSPI_WriteDirectCommValue(FLASH_INSTR_ERASE_4KB_SECTOR);
  288.         QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF0000ul) >> 16));
  289.         QSPI_WriteDirectCommValue((uint8_t)((u32Addr & 0xFF00u) >> 8));
  290.         QSPI_WriteDirectCommValue((uint8_t)(u32Addr & 0xFFu));
  291.         QSPI_ExitDirectCommMode();
  292.         /* Wait for flash idle */
  293.         enRet = QspiFlash_WaitForWriteEnd();
  294.     }

  295.     return enRet;
  296. }

  297. /**
  298. *******************************************************************************
  299. ** \brief QSPI flash erase chip function
  300. **
  301. ** \param [in] None
  302. **
  303. ** \retval None
  304. **
  305. ******************************************************************************/
  306. void QspiFlash_EraseChip(void)
  307. {
  308.     QspiFlash_WriteEnable();
  309.     /* Send instruction to flash */
  310.     QSPI_EnterDirectCommMode();
  311.     QSPI_WriteDirectCommValue(FLASH_INSTR_ERASE_CHIP);
  312.     QSPI_ExitDirectCommMode();
  313.     /* Wait for flash idle */
  314.     QspiFlash_WaitForWriteEnd();
  315. }

  316. /**
  317. *******************************************************************************
  318. ** \brief QSPI flash read status register function
  319. **
  320. ** \param [in] u8Reg                       Need to get status register
  321. ** \arg FLASH_INSTR_READ_SR1               Status register 1
  322. ** \arg FLASH_INSTR_READ_SR2               Status register 2
  323. ** \arg FLASH_INSTR_READ_SR3               Status register 3
  324. **
  325. ** \retval uint8_t                         Current register value
  326. **
  327. ******************************************************************************/
  328. uint8_t QspiFlash_ReadStatusRegister(uint8_t u8Reg)
  329. {
  330.     uint8_t regSta = 0u;

  331.     QSPI_EnterDirectCommMode();
  332.     QSPI_WriteDirectCommValue(u8Reg);
  333.     regSta = QSPI_ReadDirectCommValue();
  334.     QSPI_ExitDirectCommMode();

  335.     return regSta;
  336. }

  337. /**
  338. *******************************************************************************
  339. ** \brief System clock init function
  340. **
  341. ** \param [in] None
  342. **
  343. ** \retval None
  344. **
  345. ******************************************************************************/
  346. void SystemClk_Init(void)
  347. {
  348.     stc_clk_sysclk_cfg_t    stcSysClkCfg;
  349.     stc_clk_xtal_cfg_t      stcXtalCfg;
  350.     stc_clk_mpll_cfg_t      stcMpllCfg;

  351.     MEM_ZERO_STRUCT(stcSysClkCfg);
  352.     MEM_ZERO_STRUCT(stcXtalCfg);
  353.     MEM_ZERO_STRUCT(stcMpllCfg);

  354.     /* Set bus clk div. */
  355.     stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 168MHz
  356.     stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 84MHz
  357.     stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 168MHz
  358.     stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 84MHz
  359.     stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 42MHz
  360.     stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 42MHz
  361.     stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 84MHz
  362.     CLK_SysClkConfig(&stcSysClkCfg);

  363.     /* Switch system clock source to MPLL. */
  364.     /* Use Xtal as MPLL source. */
  365.     stcXtalCfg.enMode = ClkXtalModeOsc;
  366.     stcXtalCfg.enDrv = ClkXtalLowDrv;
  367.     stcXtalCfg.enFastStartup = Enable;
  368.     CLK_XtalConfig(&stcXtalCfg);
  369.     CLK_XtalCmd(Enable);

  370.     /* MPLL config. */
  371.     stcMpllCfg.pllmDiv = 1u;
  372.     stcMpllCfg.plln = 42u;
  373.     stcMpllCfg.PllpDiv = 2u;
  374.     stcMpllCfg.PllqDiv = 2u;
  375.     stcMpllCfg.PllrDiv = 2u;
  376.     CLK_SetPllSource(ClkPllSrcXTAL);
  377.     CLK_MpllConfig(&stcMpllCfg);

  378.     /* flash read wait cycle setting */
  379.     EFM_Unlock();
  380.     EFM_SetLatency(EFM_LATENCY_4);
  381.     EFM_Lock();

  382.     /* Enable MPLL. */
  383.     CLK_MpllCmd(Enable);

  384.     /* Wait MPLL ready. */
  385.     while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
  386.     {
  387.     }

  388.     /* Switch system clock source to MPLL. */
  389.     CLK_SetSysClkSource(CLKSysSrcMPLL);
  390. }

  391. /**
  392. *******************************************************************************
  393. ** \brief  main function for QSPI four wire i/o fast read function
  394. **
  395. ** \param [in] None
  396. **
  397. ** \retval int32_t Return value, if needed
  398. **
  399. ******************************************************************************/
  400. int32_t main(void)
  401. {
  402.     uint32_t flashAddr = 0u;
  403.     uint8_t *pFlashReadAddr;
  404.     uint16_t bufferLen = 0u;
  405.     char txBuffer[] = "QSPI read and write flash example: Welcome to use HDSC micro chip";
  406.     stc_port_init_t stcPortInit;
  407.     stc_qspi_comm_protocol_t stcQspiCommProtocol;

  408.     /* configure structure initialization */
  409.     MEM_ZERO_STRUCT(stcPortInit);
  410.     MEM_ZERO_STRUCT(stcQspiCommProtocol);

  411.     /* Configure system clock frequency */
  412.     SystemClk_Init();

  413.     /* LED0 Port/Pin initialization */
  414.     LED0_OFF();
  415.     stcPortInit.enPinMode = Pin_Mode_Out;
  416.     PORT_Init(LED0_PORT, LED0_PIN, &stcPortInit);

  417.     /* LED1 Port/Pin initialization */
  418.     LED1_OFF();
  419.     stcPortInit.enPinMode = Pin_Mode_Out;
  420.     PORT_Init(LED1_PORT, LED1_PIN, &stcPortInit);

  421.     /* Key0 Port/Pin initialization */
  422.     Sw2_Init();
  423.     /* Flash initialization */
  424.     QspiFlash_Init();
  425.     /* Get tx buffer length */
  426.     bufferLen = (uint16_t)sizeof(txBuffer);

  427.     while (1)
  428.     {
  429.         if (1u == u8ExIntFlag)
  430.         {
  431.             u8ExIntFlag = 0u;
  432. //            LED0_OFF();
  433. //            LED1_OFF();
  434.             /* Switch to standard read mode */
  435.             stcQspiCommProtocol.enReadMode = QspiReadModeStandard;
  436.             QSPI_CommProtocolConfig(&stcQspiCommProtocol);
  437.             /* Erase sector */
  438.             QspiFlash_Erase4KbSector(flashAddr);
  439.             /* Write data to flash */
  440.             QspiFlash_WritePage(flashAddr, (uint8_t*)&txBuffer[0], sizeof(txBuffer));
  441.             /* Switch to four wire i/o fast read mode */
  442.             stcQspiCommProtocol.enReadMode = QspiReadModeFourWiresIO;
  443.             QSPI_CommProtocolConfig(&stcQspiCommProtocol);
  444.             /* Pointer to flash address map */
  445.             pFlashReadAddr = (uint8_t *)((uint32_t)QSPI_BUS_ADDRESS + flashAddr);
  446.             /* Compare txBuffer and flash */
  447.             if (memcmp(txBuffer, pFlashReadAddr, (uint32_t)bufferLen) != 0)
  448.             {
  449.                 LED0_TOGGLE();
  450.             }
  451.             else
  452.             {
  453.                 LED1_TOGGLE();
  454.             }
  455.             /* Flash address offset */
  456.             flashAddr += FLASH_SECTOR_SIZE;
  457.             if (flashAddr >= FLASH_MAX_ADDR)
  458.             {
  459.                 flashAddr = 0u;
  460.             }
  461.         }
  462.     }
  463. }

  464. /*******************************************************************************
  465. * EOF (not truncated)
  466. ******************************************************************************/
在给的例程中是判断读取到的数据和写入的数据是否一样来点亮LED0或者LED1,这样的话应用起来效果不明显,因为LED1如果点亮了,通过多次按键不会看出来有什么区别,因为都是同一个灯在点亮,所以我把程序作了一点修改,通过按键来翻转灯的亮灭,这样的话就可以判断出来是什么问题,而且显示的效果也比常亮好
下面是实验的图片
980966020e6bc4ac66.png
这个是上电后的状态,一直在等待按键按下,所以没有灯点亮
802576020e6e89c0a7.png
这是按键按下后,判断读取到的数据和写入的数据是一样的,点亮了这个灯,如果再次按下的话这个灯会熄灭
好了,今天就到这里,以后看有什么新的实验,我再发上来和大家一起分享,关于代码中如果有哪里不清楚的可以在本帖下方留言,我看到后会及时回复大家



wangshujun 发表于 2021-2-8 15:52 | 显示全部楼层
如果连接spiram的话是否可以用于xip的自动写入
 楼主| binoo7 发表于 2021-2-8 16:38 | 显示全部楼层
wangshujun 发表于 2021-2-8 15:52
如果连接spiram的话是否可以用于xip的自动写入

没明白楼主的意思,写入的话是有特定格式的,就像你读取片内flash一样,读取的话是自动的
wangshujun 发表于 2021-2-18 10:31 | 显示全部楼层
binoo7 发表于 2021-2-8 16:38
没明白楼主的意思,写入的话是有特定格式的,就像你读取片内flash一样,读取的话是自动的 ...

没有深入了解底层的实现,不过esp32对于挂在到qspi的ram做了处理,可以在应用中直接当作堆来用,这个体验非常好,我猜测是在编译器底层做的处理,而不是芯片自身功能,底层的程序拦截对spi区域的写访问,处理成qspi指令,读取就直接用xip来实现了
zhuotuzi 发表于 2021-2-22 23:43 | 显示全部楼层
还没了解过这个接口呢。看看。
幸福小强 发表于 2021-2-23 22:40 | 显示全部楼层
只用过SPI
幸福小强 发表于 2021-2-23 22:41 | 显示全部楼层
QSPI是什么?
SPI协议其实是包括:Standard SPI、Dual SPI和Queued SPI三种协议接口,分别对应3-wire, 4-wire, 6-wire。

(1)通常我们说的SPI就是Standard SPI,有4根信号线,分别为CLK、CS、MOSI和MISO。数据线工作在全双工。

(2)Dual SPI,它只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样mosi变成SIO0(serial io 0),mosi变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输。

(3)类似的,还可以扩展,与也是针对SPI Flash,Qual SPI Flash增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit

而QSPI就是Queued SPI的简写。
天灵灵地灵灵 发表于 2021-2-23 22:50 | 显示全部楼层
是不是速度比较快。
两只袜子 发表于 2021-2-24 09:15 | 显示全部楼层
•  支持多种读取方式
a.标准读/快速读
b.二线式输出快速读取/二线式输入输出快速读取
c.四线式输出快速读取/四线式输入输出快速读取
勇敢的大白菜 发表于 2021-2-24 09:36 | 显示全部楼层
什么叫Qspi
勇者无惧你和我 发表于 2021-2-24 09:44 | 显示全部楼层
一直没有搞明白什么叫QSPI
 楼主| binoo7 发表于 2021-2-24 13:00 | 显示全部楼层

QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。
 楼主| binoo7 发表于 2021-2-24 13:01 | 显示全部楼层
勇者无惧你和我 发表于 2021-2-24 09:44
一直没有搞明白什么叫QSPI

QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。
starforeye 发表于 2021-3-27 11:20 | 显示全部楼层
怎么读取数据?直接操作地址吗?怎么发送地址?
pzljun 发表于 2021-4-1 11:26 | 显示全部楼层
这个例程接了W25Q128,根本不能用,惧入惧入
单片小菜 发表于 2021-4-1 16:10 | 显示全部楼层
感谢楼主分享,不错的一次体验。
里面有晴雨 发表于 2021-4-1 17:31 | 显示全部楼层
感谢楼主的分享,不错的一次体验活动,棒棒的。
 楼主| binoo7 发表于 2021-4-2 13:24 | 显示全部楼层
pzljun 发表于 2021-4-1 11:26
这个例程接了W25Q128,根本不能用,惧入惧入

128需要改配置文件,没事儿的

评论

改哪里?改出来看看呀  发表于 2021-4-2 16:02
pzljun 发表于 2021-4-2 16:04 | 显示全部楼层
这玩易就是个费材,在Q S P I模式下,普通的读操作就不能进行,只能用直接模式,然而直接模式压根读不到正确的数
 楼主| binoo7 发表于 2021-4-2 16:30 | 显示全部楼层
pzljun 发表于 2021-4-2 16:04
这玩易就是个费材,在Q S P I模式下,普通的读操作就不能进行,只能用直接模式,然而直接模式压根读不到正 ...

哈哈,这个就是后期需要改进的地方了,能做到这样也挺不容易了

评论

谁改进?厂家还是用户?  发表于 2021-4-2 16:59
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

457

帖子

10

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