drv_qspi.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. /*
  2. * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-06-15 CDT first version
  9. * 2023-09-30 CDT Delete dma transmit interrupt
  10. * 2024-02-28 CDT support HC32F448
  11. * 2024-02-29 CDT Support multi line write/read
  12. * 2024-04-18 CDT support HC32F472
  13. * 2025-04-14 CDT support HC32F4A8
  14. */
  15. /*******************************************************************************
  16. * Include files
  17. ******************************************************************************/
  18. #include <rtthread.h>
  19. #include <rtdevice.h>
  20. #if defined(RT_USING_QSPI)
  21. #if defined(BSP_USING_QSPI)
  22. #include "drv_qspi.h"
  23. #include "board_config.h"
  24. /*******************************************************************************
  25. * Local type definitions ('typedef')
  26. ******************************************************************************/
  27. /*******************************************************************************
  28. * Local pre-processor symbols/macros ('#define')
  29. ******************************************************************************/
  30. // #define DRV_DEBUG
  31. #define LOG_TAG "drv.qspi"
  32. #include <drv_log.h>
  33. /* QSPI read/write function */
  34. #define QSPI_READ_FUNC (0U)
  35. #define QSPI_WRITE_FUNC (1U)
  36. /* QSPI direct communication line */
  37. #define QSPI_DIRECT_COMM_LINE_ONE (0U)
  38. #define QSPI_DIRECT_COMM_LINE_MULTI (1U)
  39. #define QSPI_BASE_BLK_SIZE (0x4000000UL)
  40. #define QSPI_MAX_FLASH_ADDR (0xFC000000UL)
  41. /* QSPI max division */
  42. #define QSPI_MAX_DIV_VAL (0x3FU) /* Div64 */
  43. /* QSPI read instruction */
  44. #define QSPI_3LINE_STD_RD (0x03U)
  45. #define QSPI_3LINE_FAST_RD (0x0BU)
  46. #define QSPI_3LINE_DUAL_OUTPUT_FAST_RD (0x3BU)
  47. #define QSPI_3LINE_DUAL_IO_FAST_RD (0xBBU)
  48. #define QSPI_3LINE_QUAD_OUTPUT_FAST_RD (0x6BU)
  49. #define QSPI_3LINE_QUAD_IO_FAST_RD (0xEBU)
  50. #define QSPI_4LINE_STD_RD (0x13U)
  51. #define QSPI_4LINE_FAST_RD (0x0CU)
  52. #define QSPI_4LINE_DUAL_OUTPUT_FAST_RD (0x3CU)
  53. #define QSPI_4LINE_DUAL_IO_FAST_RD (0xBCU)
  54. #define QSPI_4LINE_QUAD_OUTPUT_FAST_RD (0x6CU)
  55. #define QSPI_4LINE_QUAD_IO_FAST_RD (0xECU)
  56. /*******************************************************************************
  57. * Global variable definitions (declared in header file with 'extern')
  58. ******************************************************************************/
  59. extern rt_err_t rt_hw_qspi_board_init(void);
  60. /*******************************************************************************
  61. * Local function prototypes ('static')
  62. ******************************************************************************/
  63. static void qspi_err_irq_handler(void);
  64. /*******************************************************************************
  65. * Local variable definitions ('static')
  66. ******************************************************************************/
  67. #ifndef BSP_QSPI_USING_SOFT_CS
  68. static const uint8_t qspi_rom_cmd_list[] =
  69. {
  70. QSPI_3LINE_STD_RD, QSPI_3LINE_FAST_RD, QSPI_3LINE_DUAL_OUTPUT_FAST_RD,
  71. QSPI_3LINE_DUAL_IO_FAST_RD, QSPI_3LINE_QUAD_OUTPUT_FAST_RD, QSPI_3LINE_QUAD_IO_FAST_RD,
  72. QSPI_4LINE_STD_RD, QSPI_4LINE_FAST_RD, QSPI_4LINE_DUAL_OUTPUT_FAST_RD,
  73. QSPI_4LINE_DUAL_IO_FAST_RD, QSPI_4LINE_QUAD_OUTPUT_FAST_RD, QSPI_4LINE_QUAD_IO_FAST_RD,
  74. };
  75. #endif
  76. struct rt_spi_bus spi_bus_obj;
  77. struct hc32_qspi_bus qspi_bus_obj;
  78. /*******************************************************************************
  79. * Function implementation - global ('extern') and local ('static')
  80. ******************************************************************************/
  81. static int hc32_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg)
  82. {
  83. int result = RT_EOK;
  84. uint32_t u32Cnt = 1;
  85. uint32_t u32BusFreq;
  86. stc_qspi_init_t stcQspiInit = QSPI_INIT_PARAMS;
  87. RT_ASSERT(device != RT_NULL);
  88. RT_ASSERT(qspi_cfg != RT_NULL);
  89. struct rt_spi_configuration *cfg = &qspi_cfg->parent;
  90. struct hc32_qspi_bus *qspi_bus = device->parent.bus->parent.user_data;
  91. /* Get BUS clock */
  92. u32BusFreq = CLK_GetBusClockFreq(CLK_BUS_HCLK);
  93. while (cfg->max_hz < u32BusFreq / (u32Cnt + 1U))
  94. {
  95. if (++u32Cnt == QSPI_MAX_DIV_VAL) /* Div64 */
  96. {
  97. break;
  98. }
  99. }
  100. stcQspiInit.u32ClockDiv = (u32Cnt << QSPI_CR_DIV_POS);
  101. if (!(cfg->mode & RT_SPI_CPOL))
  102. {
  103. stcQspiInit.u32SpiMode = QSPI_SPI_MD0; /* QSPI MODE0 */
  104. }
  105. else
  106. {
  107. stcQspiInit.u32SpiMode = QSPI_SPI_MD3; /* QSPI MODE3 */
  108. }
  109. /* Enable qspi clock */
  110. FCG_Fcg1PeriphClockCmd(qspi_bus->config->clock, ENABLE);
  111. /* qspi port init */
  112. rt_hw_qspi_board_init();
  113. /* Init QSPI */
  114. stcQspiInit.u32ReadMode = QSPI_RD_MD_STD_RD;
  115. stcQspiInit.u32DummyCycle = QSPI_DUMMY_CYCLE4;
  116. stcQspiInit.u32AddrWidth = QSPI_ADDR_WIDTH_24BIT;
  117. (void)QSPI_Init(&stcQspiInit);
  118. QSPI_SetWpPinLevel(QSPI_WP_PIN_LEVEL);
  119. /* Enable error interrupt */
  120. NVIC_EnableIRQ(qspi_bus->config->err_irq.irq_config.irq_num);
  121. LOG_D("qspi init success!");
  122. #ifdef BSP_QSPI_USING_DMA
  123. struct dma_config *qspi_dma;
  124. stc_dma_init_t stcDmaInit;
  125. /* Get qspi dma */
  126. qspi_dma = qspi_bus->config->dma_qspi;
  127. /* Enable Dma clock */
  128. FCG_Fcg0PeriphClockCmd(qspi_dma->clock, ENABLE);
  129. /* Config Dma */
  130. DMA_StructInit(&stcDmaInit);
  131. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
  132. /* Init Dma */
  133. if (LL_OK != DMA_Init(qspi_dma->Instance, qspi_dma->channel, &stcDmaInit))
  134. {
  135. return -RT_ERROR;
  136. }
  137. DMA_Cmd(qspi_dma->Instance, ENABLE);
  138. #endif /* BSP_QSPI_USING_DMA */
  139. return result;
  140. }
  141. #ifndef BSP_QSPI_USING_SOFT_CS
  142. static int32_t hc32_qspi_search_rom_cmd(uint8_t u8Cmd)
  143. {
  144. uint32_t u32Cnt, u32ListLen;
  145. u32ListLen = sizeof(qspi_rom_cmd_list);
  146. for (u32Cnt = 0; u32Cnt < u32ListLen; u32Cnt++)
  147. {
  148. if (u8Cmd == qspi_rom_cmd_list[u32Cnt])
  149. {
  150. return LL_OK;
  151. }
  152. }
  153. return LL_ERR;
  154. }
  155. #endif
  156. static int32_t hc32_qspi_check_direct_comm_param(struct rt_qspi_message *message, uint8_t line)
  157. {
  158. if (QSPI_DIRECT_COMM_LINE_ONE == line)
  159. {
  160. if (message->instruction.qspi_lines > 1)
  161. {
  162. return LL_ERR_INVD_PARAM;
  163. }
  164. if (message->address.size != 0)
  165. {
  166. if ((message->address.qspi_lines > 1) || ((message->address.size % 8) != 0))
  167. {
  168. return LL_ERR_INVD_PARAM;
  169. }
  170. }
  171. if (message->qspi_data_lines > 1)
  172. {
  173. return LL_ERR_INVD_PARAM;
  174. }
  175. if (0U != message->dummy_cycles)
  176. {
  177. if ((message->dummy_cycles < 3) || (message->dummy_cycles > 18) || (message->dummy_cycles % 8) != 0)
  178. {
  179. return LL_ERR_INVD_PARAM;
  180. }
  181. }
  182. }
  183. else
  184. {
  185. if ((message->instruction.qspi_lines > 2) && (message->instruction.qspi_lines != 4))
  186. {
  187. return LL_ERR_INVD_PARAM;
  188. }
  189. if (message->address.size != 0)
  190. {
  191. if (((message->address.qspi_lines > 2) && (message->address.qspi_lines != 4)) ||
  192. ((message->address.size % 8) != 0))
  193. {
  194. return LL_ERR_INVD_PARAM;
  195. }
  196. }
  197. if ((message->qspi_data_lines > 2) && (message->qspi_data_lines != 4))
  198. {
  199. return LL_ERR_INVD_PARAM;
  200. }
  201. if ((0U != message->dummy_cycles) && ((message->dummy_cycles < 3) || (message->dummy_cycles > 18)))
  202. {
  203. return LL_ERR_INVD_PARAM;
  204. }
  205. if (0U != message->dummy_cycles)
  206. {
  207. if ((message->dummy_cycles < 3) || (message->dummy_cycles > 18))
  208. {
  209. return LL_ERR_INVD_PARAM;
  210. }
  211. }
  212. }
  213. return LL_OK;
  214. }
  215. static int32_t hc32_qspi_send_cmd(struct hc32_qspi_bus *qspi_bus, struct rt_qspi_message *message, uint8_t u8Func)
  216. {
  217. #ifndef BSP_QSPI_USING_SOFT_CS
  218. uint32_t u32ReadMode = QSPI_RD_MD_STD_RD;
  219. uint32_t u32DummyCycle = 0U;
  220. uint32_t u32AddrWidth;
  221. uint8_t u8Instr, u8CalcDummy = 0U;
  222. #endif
  223. RT_ASSERT(qspi_bus != RT_NULL);
  224. RT_ASSERT(message != RT_NULL);
  225. #ifndef BSP_QSPI_USING_SOFT_CS
  226. CM_QSPI_TypeDef *qspi_instance = qspi_bus->config->Instance;
  227. u8Instr = message->instruction.content;
  228. if ((QSPI_READ_FUNC == u8Func) && (LL_OK == hc32_qspi_search_rom_cmd(u8Instr)))
  229. {
  230. if ((message->instruction.qspi_lines != 1) ||
  231. ((message->address.qspi_lines != 1) && (message->address.qspi_lines != 2) && (message->address.qspi_lines != 4)) ||
  232. ((message->qspi_data_lines != 1) && (message->qspi_data_lines != 2) && (message->qspi_data_lines != 4)))
  233. {
  234. return LL_ERR_INVD_PARAM;
  235. }
  236. if (((message->address.qspi_lines == 2) && ((message->qspi_data_lines == 1) || (message->qspi_data_lines == 4))) ||
  237. ((message->address.qspi_lines == 4) && ((message->qspi_data_lines == 1) || (message->qspi_data_lines == 2))))
  238. {
  239. return LL_ERR_INVD_PARAM;
  240. }
  241. if ((message->instruction.qspi_lines == 1) && (message->address.qspi_lines == 1) && (message->qspi_data_lines == 1))
  242. {
  243. if (message->dummy_cycles != 0)
  244. {
  245. u32ReadMode += 1U;
  246. u8CalcDummy = 1U;
  247. }
  248. }
  249. else
  250. {
  251. u8CalcDummy = 1U;
  252. u32ReadMode = message->qspi_data_lines;
  253. if (message->address.qspi_lines == message->qspi_data_lines)
  254. {
  255. u32ReadMode += 1U;
  256. }
  257. }
  258. if (0U != u8CalcDummy)
  259. {
  260. if ((message->dummy_cycles < 3) || (message->dummy_cycles > 18))
  261. {
  262. return LL_ERR_INVD_PARAM;
  263. }
  264. u32DummyCycle = (message->dummy_cycles - 3) << QSPI_FCR_DMCYCN_POS;
  265. }
  266. if (message->address.size == 24)
  267. {
  268. u32AddrWidth = QSPI_ADDR_WIDTH_24BIT;
  269. }
  270. else
  271. {
  272. u32AddrWidth = QSPI_ADDR_WIDTH_32BIT_INSTR_32BIT;
  273. }
  274. /* configure register */
  275. MODIFY_REG32(qspi_instance->FCR, (QSPI_FCR_DMCYCN | QSPI_FCR_FOUR_BIC | QSPI_FCR_AWSL),
  276. (u32DummyCycle | u32AddrWidth));
  277. QSPI_SetReadMode(u32ReadMode);
  278. }
  279. else
  280. #endif
  281. {
  282. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  283. #ifndef BSP_QSPI_USING_SOFT_CS
  284. if (LL_OK != hc32_qspi_check_direct_comm_param(message, QSPI_DIRECT_COMM_LINE_ONE))
  285. {
  286. return LL_ERR_INVD_PARAM;
  287. }
  288. /* Set standard read mode */
  289. QSPI_SetReadMode(QSPI_RD_MD_STD_RD);
  290. #else
  291. if (LL_OK != hc32_qspi_check_direct_comm_param(message, QSPI_DIRECT_COMM_LINE_MULTI))
  292. {
  293. return LL_ERR_INVD_PARAM;
  294. }
  295. /* Set custom read mode */
  296. QSPI_SetReadMode(QSPI_RD_MD_CUSTOM_FAST_RD);
  297. #endif
  298. #elif defined (HC32F448) || defined (HC32F4A8)
  299. if (LL_OK != hc32_qspi_check_direct_comm_param(message, QSPI_DIRECT_COMM_LINE_MULTI))
  300. {
  301. return LL_ERR_INVD_PARAM;
  302. }
  303. #endif
  304. }
  305. return LL_OK;
  306. }
  307. static void hc32_qspi_word_to_byte(uint32_t u32Word, uint8_t *pu8Byte, uint8_t u8Len)
  308. {
  309. uint8_t u8Count = 0U;
  310. uint32_t u32ByteNum = u8Len - 1U;
  311. do
  312. {
  313. pu8Byte[u8Count++] = (uint8_t)(u32Word >> (u32ByteNum * 8U)) & 0xFFU;
  314. }
  315. while ((u32ByteNum--) != 0UL);
  316. }
  317. #if defined (HC32F448) || defined (HC32F4A8)
  318. static rt_uint32_t hc32_qspi_get_dcom_protocol_line(rt_uint8_t protocol_line)
  319. {
  320. rt_uint32_t dcom_protocol_line;
  321. switch (protocol_line)
  322. {
  323. case 2:
  324. dcom_protocol_line = QSPI_DIRECT_COMM_PROTOCOL_2LINE;
  325. break;
  326. case 4:
  327. dcom_protocol_line = QSPI_DIRECT_COMM_PROTOCOL_4LINE;
  328. break;
  329. case 1:
  330. default:
  331. dcom_protocol_line = QSPI_DIRECT_COMM_PROTOCOL_1LINE;
  332. break;
  333. }
  334. return dcom_protocol_line;
  335. }
  336. #endif
  337. static void hc32_qspi_write_direct_comm_value(rt_uint8_t protocol_line, rt_uint8_t value)
  338. {
  339. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  340. (void)protocol_line;
  341. QSPI_WriteDirectCommValue(value);
  342. #elif defined (HC32F448) || defined (HC32F4A8)
  343. QSPI_WriteDirectCommValue(hc32_qspi_get_dcom_protocol_line(protocol_line), value);
  344. #endif
  345. }
  346. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  347. #ifdef BSP_QSPI_USING_SOFT_CS
  348. static void hc32_qspi_set_trans_protocol(uint32_t u32Line)
  349. {
  350. stc_qspi_custom_mode_t stcCustomMode;
  351. stcCustomMode.u8InstrCode = 0U;
  352. switch (u32Line)
  353. {
  354. case 2:
  355. stcCustomMode.u32InstrProtocol = QSPI_INSTR_PROTOCOL_2LINE;
  356. stcCustomMode.u32AddrProtocol = QSPI_ADDR_PROTOCOL_2LINE;
  357. stcCustomMode.u32DataProtocol = QSPI_DATA_PROTOCOL_2LINE;
  358. break;
  359. case 4:
  360. stcCustomMode.u32InstrProtocol = QSPI_INSTR_PROTOCOL_4LINE;
  361. stcCustomMode.u32AddrProtocol = QSPI_ADDR_PROTOCOL_4LINE;
  362. stcCustomMode.u32DataProtocol = QSPI_DATA_PROTOCOL_4LINE;
  363. break;
  364. case 1:
  365. default:
  366. stcCustomMode.u32InstrProtocol = QSPI_INSTR_PROTOCOL_1LINE;
  367. stcCustomMode.u32AddrProtocol = QSPI_ADDR_PROTOCOL_1LINE;
  368. stcCustomMode.u32DataProtocol = QSPI_DATA_PROTOCOL_1LINE;
  369. break;
  370. }
  371. QSPI_CustomReadConfig(&stcCustomMode);
  372. }
  373. #endif
  374. #endif
  375. static int32_t hc32_qspi_write_instr(struct hc32_qspi_bus *qspi_bus, struct rt_qspi_message *message,
  376. uint8_t u8Instr, uint32_t u32InstrLen, uint8_t *pu8Addr, uint32_t u32AddrLen,
  377. const uint8_t *pu8WriteBuf, uint32_t u32BufLen)
  378. {
  379. uint32_t u32Count;
  380. int32_t i32Ret = LL_OK;
  381. #ifdef BSP_QSPI_USING_DMA
  382. struct dma_config *qspi_dma;
  383. stc_dma_init_t stcDmaInit;
  384. uint32_t u32DmaTransSize;
  385. uint32_t u32TxIndex = 0U;
  386. rt_uint32_t u32TimeoutCnt;
  387. rt_uint32_t src_addr;
  388. #endif
  389. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  390. #ifndef BSP_QSPI_USING_SOFT_CS
  391. /* Enter direct communication mode */
  392. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  393. #endif
  394. #elif defined (HC32F448) || defined (HC32F4A8)
  395. /* Enter direct communication mode */
  396. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  397. #endif
  398. if (0UL != u32InstrLen)
  399. {
  400. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  401. #ifdef BSP_QSPI_USING_SOFT_CS
  402. hc32_qspi_set_trans_protocol(message->instruction.qspi_lines);
  403. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  404. #endif
  405. #endif
  406. hc32_qspi_write_direct_comm_value(message->instruction.qspi_lines, u8Instr);
  407. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  408. #ifdef BSP_QSPI_USING_SOFT_CS
  409. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  410. #endif
  411. #endif
  412. }
  413. if ((NULL != pu8Addr) && (0UL != u32AddrLen))
  414. {
  415. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  416. #ifdef BSP_QSPI_USING_SOFT_CS
  417. hc32_qspi_set_trans_protocol(message->address.qspi_lines);
  418. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  419. #endif
  420. #endif
  421. for (u32Count = 0UL; u32Count < u32AddrLen; u32Count++)
  422. {
  423. hc32_qspi_write_direct_comm_value(message->address.qspi_lines, pu8Addr[u32Count]);
  424. }
  425. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  426. #ifdef BSP_QSPI_USING_SOFT_CS
  427. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  428. #endif
  429. #endif
  430. }
  431. if ((NULL != pu8WriteBuf) && (0UL != u32BufLen))
  432. {
  433. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  434. #ifdef BSP_QSPI_USING_SOFT_CS
  435. hc32_qspi_set_trans_protocol(message->qspi_data_lines);
  436. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  437. #endif
  438. #endif
  439. #ifdef BSP_QSPI_USING_DMA
  440. qspi_dma = qspi_bus->config->dma_qspi;
  441. AOS_SetTriggerEventSrc(qspi_dma->trigger_select, qspi_dma->trigger_event);
  442. /* Config Dma */
  443. DMA_StructInit(&stcDmaInit);
  444. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  445. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
  446. #elif defined (HC32F448) || defined (HC32F4A8)
  447. rt_uint16_t dcom_line = (rt_uint16_t)hc32_qspi_get_dcom_protocol_line(message->qspi_data_lines);
  448. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_16BIT;
  449. #endif
  450. stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_INC;
  451. stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;
  452. DMA_Init(qspi_dma->Instance, qspi_dma->channel, &stcDmaInit);
  453. while (u32BufLen != 0U)
  454. {
  455. if (u32BufLen > DMA_DTCTL_BLKSIZE)
  456. {
  457. u32DmaTransSize = DMA_DTCTL_BLKSIZE;
  458. u32BufLen -= DMA_DTCTL_BLKSIZE;
  459. }
  460. else
  461. {
  462. u32DmaTransSize = u32BufLen;
  463. u32BufLen = 0U;
  464. }
  465. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  466. src_addr = (rt_uint32_t)&pu8WriteBuf[u32TxIndex];
  467. #elif defined (HC32F448) || defined (HC32F4A8)
  468. if (u32DmaTransSize > qspi_bus->config->dma_tx_buf_size)
  469. {
  470. LOG_E("qspi dma transmit size over buffer size!");
  471. i32Ret = LL_ERR;
  472. break;
  473. }
  474. for (rt_uint32_t i = 0; i < u32DmaTransSize; i++)
  475. {
  476. qspi_bus->config->dma_tx_buf[i] = (rt_uint16_t)pu8WriteBuf[u32TxIndex + i] | dcom_line;
  477. }
  478. src_addr = (rt_uint32_t)qspi_bus->config->dma_tx_buf;
  479. #endif
  480. DMA_ClearTransCompleteStatus(qspi_dma->Instance, qspi_dma->flag);
  481. DMA_SetSrcAddr(qspi_dma->Instance, qspi_dma->channel, src_addr);
  482. DMA_SetDestAddr(qspi_dma->Instance, qspi_dma->channel, (uint32_t)&qspi_bus->config->Instance->DCOM);
  483. DMA_SetTransCount(qspi_dma->Instance, qspi_dma->channel, 1UL);
  484. DMA_SetBlockSize(qspi_dma->Instance, qspi_dma->channel, (uint16_t)u32DmaTransSize);
  485. (void)DMA_ChCmd(qspi_dma->Instance, qspi_dma->channel, ENABLE);
  486. AOS_SW_Trigger(); /* 1st trigger for DMA */
  487. u32TimeoutCnt = 0U;
  488. /* Wait DMA transfer completed */
  489. while ((RESET == DMA_GetTransCompleteStatus(qspi_dma->Instance, qspi_dma->flag)) &&
  490. (u32TimeoutCnt < qspi_bus->config->timeout))
  491. {
  492. rt_thread_mdelay(1);
  493. u32TimeoutCnt++;
  494. }
  495. if (u32TimeoutCnt >= qspi_bus->config->timeout)
  496. {
  497. i32Ret = LL_ERR_TIMEOUT;
  498. break;
  499. }
  500. u32TxIndex += u32DmaTransSize;
  501. }
  502. #else
  503. for (u32Count = 0UL; u32Count < u32BufLen; u32Count++)
  504. {
  505. hc32_qspi_write_direct_comm_value(message->qspi_data_lines, pu8WriteBuf[u32Count]);
  506. }
  507. #endif
  508. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  509. #ifdef BSP_QSPI_USING_SOFT_CS
  510. /* Exit direct communication mode */
  511. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  512. #endif
  513. #endif
  514. }
  515. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  516. #ifndef BSP_QSPI_USING_SOFT_CS
  517. /* Exit direct communication mode */
  518. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  519. #endif
  520. #elif defined (HC32F448) || defined (HC32F4A8)
  521. /* Exit direct communication mode */
  522. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  523. #endif
  524. return i32Ret;
  525. }
  526. static int32_t hc32_qspi_read_instr(struct hc32_qspi_bus *qspi_bus, struct rt_qspi_message *message,
  527. uint8_t u8Instr, uint32_t u32InstrLen, uint8_t *pu8Addr, uint32_t u32AddrLen,
  528. uint8_t *pu8ReadBuf, uint32_t u32BufLen)
  529. {
  530. uint32_t u32Count;
  531. int32_t i32Ret = LL_OK;
  532. #ifdef BSP_QSPI_USING_DMA
  533. struct dma_config *qspi_dma;
  534. stc_dma_init_t stcDmaInit;
  535. uint32_t u32DmaTransSize;
  536. uint32_t u32RxIndex = 0U;
  537. rt_uint32_t u32TimeoutCnt;
  538. #endif
  539. #if defined (HC32F448) || defined (HC32F4A8)
  540. rt_uint32_t u32ReadMd;
  541. #endif
  542. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  543. #ifndef BSP_QSPI_USING_SOFT_CS
  544. /* Enter direct communication mode */
  545. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  546. #endif
  547. #elif defined (HC32F448) || defined (HC32F4A8)
  548. if ((message->instruction.qspi_lines == 4) || (message->address.qspi_lines == 4) ||
  549. (message->qspi_data_lines == 4))
  550. {
  551. u32ReadMd = READ_REG32_BIT(CM_QSPI->CR, QSPI_CR_MDSEL);
  552. QSPI_SetReadMode(QSPI_RD_MD_QUAD_IO_FAST_RD);
  553. }
  554. /* Enter direct communication mode */
  555. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  556. #endif
  557. if (0UL != u32InstrLen)
  558. {
  559. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  560. #ifdef BSP_QSPI_USING_SOFT_CS
  561. hc32_qspi_set_trans_protocol(message->instruction.qspi_lines);
  562. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  563. #endif
  564. #endif
  565. hc32_qspi_write_direct_comm_value(message->instruction.qspi_lines, u8Instr);
  566. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  567. #ifdef BSP_QSPI_USING_SOFT_CS
  568. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  569. #endif
  570. #endif
  571. }
  572. if ((NULL != pu8Addr) && (0UL != u32AddrLen))
  573. {
  574. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  575. #ifdef BSP_QSPI_USING_SOFT_CS
  576. hc32_qspi_set_trans_protocol(message->address.qspi_lines);
  577. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  578. #endif
  579. #endif
  580. for (u32Count = 0UL; u32Count < u32AddrLen; u32Count++)
  581. {
  582. hc32_qspi_write_direct_comm_value(message->address.qspi_lines, pu8Addr[u32Count]);
  583. }
  584. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  585. #ifdef BSP_QSPI_USING_SOFT_CS
  586. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  587. #endif
  588. #endif
  589. }
  590. if ((NULL != pu8ReadBuf) && (0UL != u32BufLen))
  591. {
  592. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  593. #ifdef BSP_QSPI_USING_SOFT_CS
  594. hc32_qspi_set_trans_protocol(message->qspi_data_lines);
  595. SET_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  596. #endif
  597. #endif
  598. #ifdef BSP_QSPI_USING_DMA
  599. qspi_dma = qspi_bus->config->dma_qspi;
  600. AOS_SetTriggerEventSrc(qspi_dma->trigger_select, qspi_dma->trigger_event);
  601. /* Config Dma */
  602. DMA_StructInit(&stcDmaInit);
  603. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
  604. stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_FIX;
  605. stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_INC;
  606. DMA_Init(qspi_dma->Instance, qspi_dma->channel, &stcDmaInit);
  607. while (u32BufLen != 0U)
  608. {
  609. if (u32BufLen > DMA_DTCTL_BLKSIZE)
  610. {
  611. u32DmaTransSize = DMA_DTCTL_BLKSIZE;
  612. u32BufLen -= DMA_DTCTL_BLKSIZE;
  613. }
  614. else
  615. {
  616. u32DmaTransSize = u32BufLen;
  617. u32BufLen = 0U;
  618. }
  619. DMA_ClearTransCompleteStatus(qspi_dma->Instance, qspi_dma->flag);
  620. DMA_SetSrcAddr(qspi_dma->Instance, qspi_dma->channel, (uint32_t)&qspi_bus->config->Instance->DCOM);
  621. DMA_SetDestAddr(qspi_dma->Instance, qspi_dma->channel, (uint32_t)&pu8ReadBuf[u32RxIndex]);
  622. DMA_SetTransCount(qspi_dma->Instance, qspi_dma->channel, 1UL);
  623. DMA_SetBlockSize(qspi_dma->Instance, qspi_dma->channel, (uint16_t)u32DmaTransSize);
  624. (void)DMA_ChCmd(qspi_dma->Instance, qspi_dma->channel, ENABLE);
  625. AOS_SW_Trigger(); /* 1st trigger for DMA */
  626. u32TimeoutCnt = 0U;
  627. /* Wait DMA transfer completed */
  628. while ((RESET == DMA_GetTransCompleteStatus(qspi_dma->Instance, qspi_dma->flag)) &&
  629. (u32TimeoutCnt < qspi_bus->config->timeout))
  630. {
  631. rt_thread_mdelay(1);
  632. u32TimeoutCnt++;
  633. }
  634. if (u32TimeoutCnt >= qspi_bus->config->timeout)
  635. {
  636. i32Ret = LL_ERR_TIMEOUT;
  637. break;
  638. }
  639. u32RxIndex += u32DmaTransSize;
  640. }
  641. #else
  642. for (u32Count = 0UL; u32Count < u32BufLen; u32Count++)
  643. {
  644. pu8ReadBuf[u32Count] = QSPI_ReadDirectCommValue();
  645. }
  646. #endif
  647. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  648. #ifdef BSP_QSPI_USING_SOFT_CS
  649. /* Exit direct communication mode */
  650. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  651. #endif
  652. #endif
  653. }
  654. #if defined (HC32F460) || defined (HC32F4A0) || defined (HC32F472)
  655. #ifndef BSP_QSPI_USING_SOFT_CS
  656. /* Exit direct communication mode */
  657. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  658. #endif
  659. #elif defined (HC32F448) || defined (HC32F4A8)
  660. if ((message->instruction.qspi_lines == 4) || (message->address.qspi_lines == 4) ||
  661. (message->qspi_data_lines == 4))
  662. {
  663. QSPI_SetReadMode(u32ReadMd);
  664. }
  665. /* Exit direct communication mode */
  666. CLR_REG32_BIT(CM_QSPI->CR, QSPI_CR_DCOME);
  667. #endif
  668. return i32Ret;
  669. }
  670. static int32_t hc32_qspi_write(struct hc32_qspi_bus *qspi_bus, struct rt_qspi_message *message)
  671. {
  672. uint32_t u32Count = 0U;
  673. const rt_uint8_t *tx_buf = message->parent.send_buf;
  674. rt_int32_t length = message->parent.length;
  675. uint32_t u32Addr = message->address.content;
  676. uint8_t u8Instr = message->instruction.content;
  677. uint8_t u8AddrBuf[32];
  678. uint32_t u32AddrLen = 0U, u32DummyLen = 0U;
  679. uint32_t u32InstrLen = 0U;
  680. int32_t i32Ret;
  681. RT_ASSERT(qspi_bus != RT_NULL);
  682. RT_ASSERT(message != RT_NULL);
  683. if (message->instruction.qspi_lines != 0)
  684. {
  685. u32InstrLen = 1U;
  686. }
  687. if (message->address.size != 0)
  688. {
  689. u32AddrLen = message->address.size / 8;
  690. hc32_qspi_word_to_byte(u32Addr, u8AddrBuf, u32AddrLen);
  691. }
  692. if (message->dummy_cycles != 0)
  693. {
  694. u32DummyLen = message->dummy_cycles * message->address.qspi_lines / 8;
  695. for (u32Count = 0; u32Count < u32DummyLen; u32Count++)
  696. {
  697. u8AddrBuf[u32AddrLen] = 0xFF;
  698. u32AddrLen += 1;
  699. }
  700. }
  701. i32Ret = hc32_qspi_write_instr(qspi_bus, message, u8Instr, u32InstrLen, u8AddrBuf, u32AddrLen, tx_buf, length);
  702. return i32Ret;
  703. }
  704. static int32_t hc32_qspi_read(struct hc32_qspi_bus *qspi_bus, struct rt_qspi_message *message)
  705. {
  706. uint32_t u32Count = 0U;
  707. rt_uint8_t *rx_buf = message->parent.recv_buf;
  708. rt_int32_t length = message->parent.length;
  709. uint32_t u32Addr = message->address.content;
  710. uint8_t u8Instr = message->instruction.content;
  711. uint8_t u8AddrBuf[32];
  712. uint32_t u32AddrLen = 0U, u32DummyLen = 0U;
  713. uint32_t u32InstrLen = 0U;
  714. int32_t i32Ret = LL_OK;
  715. #ifndef BSP_QSPI_USING_SOFT_CS
  716. uint32_t u32ExtBlkStartNum = 0U;
  717. uint32_t u32GetSize, u32RxIndex = 0U;
  718. #ifdef BSP_QSPI_USING_DMA
  719. struct dma_config *qspi_dma;
  720. stc_dma_init_t stcDmaInit;
  721. uint32_t u32DmaTransSize;
  722. rt_uint32_t u32TimeoutCnt;
  723. #else
  724. __IO uint8_t *pu8Read;
  725. #endif
  726. #endif
  727. RT_ASSERT(qspi_bus != RT_NULL);
  728. RT_ASSERT(message != RT_NULL);
  729. #ifndef BSP_QSPI_USING_SOFT_CS
  730. if (LL_OK == hc32_qspi_search_rom_cmd(u8Instr))
  731. {
  732. u32ExtBlkStartNum = u32Addr / QSPI_BASE_BLK_SIZE;
  733. if ((u32Addr + length) > QSPI_MAX_FLASH_ADDR)
  734. {
  735. return LL_ERR_INVD_PARAM;
  736. }
  737. u32Addr = (u32Addr % QSPI_BASE_BLK_SIZE) + QSPI_ROM_BASE;
  738. #ifdef BSP_QSPI_USING_DMA
  739. qspi_dma = qspi_bus->config->dma_qspi;
  740. AOS_SetTriggerEventSrc(qspi_dma->trigger_select, qspi_dma->trigger_event);
  741. /* Config Dma */
  742. DMA_StructInit(&stcDmaInit);
  743. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
  744. stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_INC;
  745. stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_INC;
  746. DMA_Init(qspi_dma->Instance, qspi_dma->channel, &stcDmaInit);
  747. while (length != 0)
  748. {
  749. QSPI_SelectMemoryBlock((uint8_t)u32ExtBlkStartNum);
  750. if ((u32Addr + length) > (QSPI_ROM_END + 1U))
  751. {
  752. u32GetSize = (QSPI_ROM_END + 1U) - u32Addr;
  753. length -= u32GetSize;
  754. }
  755. else
  756. {
  757. u32GetSize = length;
  758. length = 0U;
  759. }
  760. while (u32GetSize != 0U)
  761. {
  762. if (u32GetSize > DMA_DTCTL_BLKSIZE)
  763. {
  764. u32DmaTransSize = DMA_DTCTL_BLKSIZE;
  765. u32GetSize -= DMA_DTCTL_BLKSIZE;
  766. }
  767. else
  768. {
  769. u32DmaTransSize = u32GetSize;
  770. u32GetSize = 0U;
  771. }
  772. DMA_ClearTransCompleteStatus(qspi_dma->Instance, qspi_dma->flag);
  773. DMA_SetSrcAddr(qspi_dma->Instance, qspi_dma->channel, u32Addr);
  774. DMA_SetDestAddr(qspi_dma->Instance, qspi_dma->channel, (uint32_t)&rx_buf[u32RxIndex]);
  775. DMA_SetTransCount(qspi_dma->Instance, qspi_dma->channel, 1UL);
  776. DMA_SetBlockSize(qspi_dma->Instance, qspi_dma->channel, (uint16_t)u32DmaTransSize);
  777. (void)DMA_ChCmd(qspi_dma->Instance, qspi_dma->channel, ENABLE);
  778. AOS_SW_Trigger(); /* 1st trigger for DMA */
  779. u32TimeoutCnt = 0U;
  780. /* Wait DMA transfer completed */
  781. while ((RESET == DMA_GetTransCompleteStatus(qspi_dma->Instance, qspi_dma->flag)) &&
  782. (u32TimeoutCnt < qspi_bus->config->timeout))
  783. {
  784. rt_thread_mdelay(1);
  785. u32TimeoutCnt++;
  786. }
  787. if (u32TimeoutCnt >= qspi_bus->config->timeout)
  788. {
  789. return LL_ERR_TIMEOUT;
  790. }
  791. u32Addr += u32DmaTransSize;
  792. u32RxIndex += u32DmaTransSize;
  793. }
  794. if (length != 0U)
  795. {
  796. u32ExtBlkStartNum += 1U;
  797. u32Addr = QSPI_ROM_BASE;
  798. }
  799. }
  800. #else
  801. while (length != 0)
  802. {
  803. QSPI_SelectMemoryBlock((uint8_t)u32ExtBlkStartNum);
  804. pu8Read = (__IO uint8_t *)u32Addr;
  805. if ((u32Addr + length) > (QSPI_ROM_END + 1U))
  806. {
  807. u32GetSize = (QSPI_ROM_END + 1U) - u32Addr;
  808. length -= u32GetSize;
  809. }
  810. else
  811. {
  812. u32GetSize = length;
  813. length = 0U;
  814. }
  815. u32Count = 0U;
  816. while (u32Count < u32GetSize)
  817. {
  818. rx_buf[u32RxIndex++] = *pu8Read++;
  819. u32Count++;
  820. }
  821. if (length != 0U)
  822. {
  823. u32ExtBlkStartNum += 1U;
  824. u32Addr = QSPI_ROM_BASE;
  825. }
  826. }
  827. #endif
  828. }
  829. else
  830. #endif
  831. {
  832. if (message->instruction.qspi_lines != 0)
  833. {
  834. u32InstrLen = 1U;
  835. }
  836. if (message->address.size != 0)
  837. {
  838. u32AddrLen = message->address.size / 8;
  839. hc32_qspi_word_to_byte(u32Addr, u8AddrBuf, u32AddrLen);
  840. }
  841. if (message->dummy_cycles != 0)
  842. {
  843. u32DummyLen = message->dummy_cycles * message->address.qspi_lines / 8;
  844. for (u32Count = 0; u32Count < u32DummyLen; u32Count++)
  845. {
  846. u8AddrBuf[u32AddrLen] = 0xFF;
  847. u32AddrLen += 1;
  848. }
  849. }
  850. i32Ret = hc32_qspi_read_instr(qspi_bus, message, u8Instr, u32InstrLen, u8AddrBuf, u32AddrLen, rx_buf, length);
  851. }
  852. return i32Ret;
  853. }
  854. static rt_ssize_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
  855. {
  856. RT_ASSERT(device != RT_NULL);
  857. RT_ASSERT(device->bus != RT_NULL);
  858. rt_size_t len = 0;
  859. struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
  860. struct hc32_qspi_bus *qspi_bus = device->bus->parent.user_data;
  861. #ifdef BSP_QSPI_USING_SOFT_CS
  862. struct hc32_hw_qspi_cs *cs = device->parent.user_data;
  863. #endif
  864. rt_int32_t length = message->length;
  865. #ifdef BSP_QSPI_USING_SOFT_CS
  866. if (message->cs_take)
  867. {
  868. rt_pin_write(cs->pin, 0);
  869. }
  870. #endif
  871. if (message->send_buf != NULL) /* send data */
  872. {
  873. if (LL_OK != hc32_qspi_send_cmd(qspi_bus, qspi_message, QSPI_WRITE_FUNC))
  874. {
  875. LOG_E("QSPI rt_qspi_message format error!");
  876. goto __exit;
  877. }
  878. if (LL_OK == hc32_qspi_write(qspi_bus, qspi_message))
  879. {
  880. if (qspi_message->parent.length != 0)
  881. {
  882. len = length;
  883. }
  884. else
  885. {
  886. len = 1;
  887. }
  888. }
  889. else
  890. {
  891. LOG_E("QSPI send data failed!");
  892. goto __exit;
  893. }
  894. }
  895. else if (message->recv_buf != NULL) /* recv data */
  896. {
  897. if (LL_OK != hc32_qspi_send_cmd(qspi_bus, qspi_message, QSPI_READ_FUNC))
  898. {
  899. LOG_E("QSPI rt_qspi_message format error!");
  900. goto __exit;
  901. }
  902. if (LL_OK == hc32_qspi_read(qspi_bus, qspi_message))
  903. {
  904. len = length;
  905. }
  906. else
  907. {
  908. LOG_E("QSPI recv data failed!");
  909. goto __exit;
  910. }
  911. }
  912. __exit:
  913. #ifdef BSP_QSPI_USING_SOFT_CS
  914. if (message->cs_release)
  915. {
  916. rt_pin_write(cs->pin, 1);
  917. }
  918. #endif
  919. return len;
  920. }
  921. static rt_err_t qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  922. {
  923. RT_ASSERT(device != RT_NULL);
  924. RT_ASSERT(configuration != RT_NULL);
  925. struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
  926. return hc32_qspi_init(qspi_device, &qspi_device->config);
  927. }
  928. static const struct rt_spi_ops hc32_qspi_ops =
  929. {
  930. .configure = qspi_configure,
  931. .xfer = qspixfer,
  932. };
  933. static int hc32_qspi_register_bus(struct hc32_qspi_bus *qspi_bus, const char *name)
  934. {
  935. RT_ASSERT(qspi_bus != RT_NULL);
  936. RT_ASSERT(name != RT_NULL);
  937. spi_bus_obj.parent.user_data = qspi_bus;
  938. return rt_qspi_bus_register(&spi_bus_obj, name, &hc32_qspi_ops);
  939. }
  940. static void qspi_err_irq_handler(void)
  941. {
  942. /* enter interrupt */
  943. rt_interrupt_enter();
  944. QSPI_ClearStatus(QSPI_FLAG_ROM_ACCESS_ERR);
  945. /* leave interrupt */
  946. rt_interrupt_leave();
  947. }
  948. #if defined (HC32F448) || defined (HC32F472)
  949. void QSPI_Handler(void)
  950. {
  951. qspi_err_irq_handler();
  952. }
  953. #endif
  954. /**
  955. * @brief This function attach device to QSPI bus.
  956. * @param bus_name QSPI bus name
  957. * @param device_name QSPI device name
  958. * @param pin QSPI cs pin number
  959. * @param data_line_width QSPI data lines width, such as 1, 2, 4
  960. * @param enter_qspi_mode Callback function that lets FLASH enter QSPI mode
  961. * @param exit_qspi_mode Callback function that lets FLASH exit QSPI mode
  962. * @retval 0 : success
  963. * -1 : failed
  964. */
  965. rt_err_t rt_hw_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint32_t pin, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)())
  966. {
  967. struct rt_qspi_device *qspi_device = RT_NULL;
  968. struct hc32_hw_qspi_cs *cs_pin = RT_NULL;
  969. rt_err_t result = RT_EOK;
  970. RT_ASSERT(bus_name != RT_NULL);
  971. RT_ASSERT(device_name != RT_NULL);
  972. RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
  973. qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
  974. if (qspi_device == RT_NULL)
  975. {
  976. LOG_E("no memory, qspi bus attach device failed!");
  977. result = RT_ENOMEM;
  978. goto __exit;
  979. }
  980. cs_pin = (struct hc32_hw_qspi_cs *)rt_malloc(sizeof(struct hc32_hw_qspi_cs));
  981. if (qspi_device == RT_NULL)
  982. {
  983. LOG_E("no memory, qspi bus attach device failed!");
  984. result = RT_ENOMEM;
  985. goto __exit;
  986. }
  987. qspi_device->enter_qspi_mode = enter_qspi_mode;
  988. qspi_device->exit_qspi_mode = exit_qspi_mode;
  989. qspi_device->config.qspi_dl_width = data_line_width;
  990. cs_pin->pin = pin;
  991. #ifdef BSP_QSPI_USING_SOFT_CS
  992. rt_pin_mode(pin, PIN_MODE_OUTPUT);
  993. rt_pin_write(pin, 1);
  994. #endif
  995. result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, (void *)cs_pin);
  996. __exit:
  997. if (result != RT_EOK)
  998. {
  999. if (qspi_device)
  1000. {
  1001. rt_free(qspi_device);
  1002. }
  1003. if (cs_pin)
  1004. {
  1005. rt_free(cs_pin);
  1006. }
  1007. }
  1008. return result;
  1009. }
  1010. static void hc32_get_qspi_info(void)
  1011. {
  1012. static struct hc32_qspi_config qspi_config = QSPI_BUS_CONFIG;
  1013. qspi_config.err_irq.irq_callback = qspi_err_irq_handler;
  1014. #ifdef BSP_QSPI_USING_DMA
  1015. static struct dma_config qspi_dma = QSPI_DMA_CONFIG;
  1016. qspi_config.dma_qspi = &qspi_dma;
  1017. #if defined (HC32F448) || defined (HC32F4A8)
  1018. qspi_config.dma_tx_buf_size = QSPI_DMA_TX_BUFSIZE;
  1019. qspi_config.dma_tx_buf = rt_malloc(qspi_config.dma_tx_buf_size << 1);
  1020. #endif
  1021. #endif
  1022. qspi_bus_obj.config = &qspi_config;
  1023. }
  1024. static int rt_hw_qspi_bus_init(void)
  1025. {
  1026. hc32_get_qspi_info();
  1027. /* register the handle */
  1028. hc32_install_irq_handler(&qspi_bus_obj.config->err_irq.irq_config, qspi_bus_obj.config->err_irq.irq_callback, RT_FALSE);
  1029. return hc32_qspi_register_bus(&qspi_bus_obj, "qspi1");
  1030. }
  1031. INIT_BOARD_EXPORT(rt_hw_qspi_bus_init);
  1032. #endif /* BSP_USING_QSPI */
  1033. #endif /* RT_USING_QSPI */