fsl_flexspi.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /*
  2. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2017 NXP
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * o Redistributions of source code must retain the above copyright notice, this list
  9. * of conditions and the following disclaimer.
  10. *
  11. * o Redistributions in binary form must reproduce the above copyright notice, this
  12. * list of conditions and the following disclaimer in the documentation and/or
  13. * other materials provided with the distribution.
  14. *
  15. * o Neither the name of the copyright holder nor the names of its
  16. * contributors may be used to endorse or promote products derived from this
  17. * software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  23. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "fsl_flexspi.h"
  31. /*******************************************************************************
  32. * Definitations
  33. ******************************************************************************/
  34. #define FREQ_1MHz (1000000UL)
  35. #define FLEXSPI_DLLCR_DEFAULT (0x100UL)
  36. #define FLEXSPI_LUT_KEY_VAL (0x5AF05AF0ul)
  37. enum
  38. {
  39. kFLEXSPI_DelayCellUnitMin = 75, /* 75ps. */
  40. kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
  41. };
  42. /*! @brief Common sets of flags used by the driver. */
  43. enum _flexspi_flag_constants
  44. {
  45. /*! IRQ sources enabled by the non-blocking transactional API. */
  46. kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmpltyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
  47. kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
  48. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag,
  49. /*! Errors to check for. */
  50. kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
  51. kFLEXSPI_IpCommandGrantTimeoutFlag,
  52. };
  53. enum _flexspi_transfer_state
  54. {
  55. kFLEXSPI_Idle = 0x0U, /*!< Transfer is done. */
  56. kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */
  57. kFLEXSPI_BusyRead = 0x2U, /*!< FLEXSPI is busy write transfer. */
  58. };
  59. /*! @brief Typedef for interrupt handler. */
  60. typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, void *flexspiHandle);
  61. /*******************************************************************************
  62. * Prototypes
  63. ******************************************************************************/
  64. /*!
  65. * @brief Get the instance number for FLEXSPI.
  66. *
  67. * @param base FLEXSPI base pointer.
  68. */
  69. uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base);
  70. /*!
  71. * @brief Configure flash A/B sample clock DLL.
  72. *
  73. * @param base FLEXSPI base pointer.
  74. * @param config Flash configuration parameters.
  75. */
  76. static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
  77. /*!
  78. * @brief Check and clear IP command execution errors.
  79. *
  80. * @param base FLEXSPI base pointer.
  81. * @param status interrupt status.
  82. */
  83. status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status);
  84. /*******************************************************************************
  85. * Variables
  86. ******************************************************************************/
  87. /*! @brief Pointers to flexspi handles for each instance. */
  88. static void *s_flexspiHandle[FSL_FEATURE_SOC_FLEXSPI_COUNT];
  89. /*! @brief Pointers to flexspi bases for each instance. */
  90. static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
  91. /*! @brief Pointers to flexspi IRQ number for each instance. */
  92. static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
  93. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  94. /* Clock name array */
  95. static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
  96. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  97. /*******************************************************************************
  98. * Code
  99. ******************************************************************************/
  100. uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
  101. {
  102. uint32_t instance;
  103. /* Find the instance index from base address mappings. */
  104. for (instance = 0; instance < FSL_FEATURE_SOC_FLEXSPI_COUNT; instance++)
  105. {
  106. if (s_flexspiBases[instance] == base)
  107. {
  108. break;
  109. }
  110. }
  111. assert(instance < FSL_FEATURE_SOC_FLEXSPI_COUNT);
  112. return instance;
  113. }
  114. static uint32_t FLEXSPI_ConfigureDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
  115. {
  116. bool isUnifiedConfig = true;
  117. uint32_t flexspiDllValue;
  118. uint32_t dllValue;
  119. uint32_t temp;
  120. uint8_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
  121. switch (rxSampleClock)
  122. {
  123. case kFLEXSPI_ReadSampleClkLoopbackInternally:
  124. case kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
  125. case kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
  126. isUnifiedConfig = true;
  127. break;
  128. case kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
  129. if (config->isSck2Enabled)
  130. {
  131. isUnifiedConfig = true;
  132. }
  133. else
  134. {
  135. isUnifiedConfig = false;
  136. }
  137. break;
  138. default:
  139. break;
  140. }
  141. if (isUnifiedConfig)
  142. {
  143. flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
  144. }
  145. else
  146. {
  147. if (config->flexspiRootClk >= 100 * FREQ_1MHz)
  148. {
  149. /* DLLEN = 1, SLVDLYTARGET = 0xF, */
  150. flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
  151. }
  152. else
  153. {
  154. temp = config->dataValidTime * 1000; /* Convert data valid time in ns to ps. */
  155. dllValue = temp / kFLEXSPI_DelayCellUnitMin;
  156. if (dllValue * kFLEXSPI_DelayCellUnitMin < temp)
  157. {
  158. dllValue++;
  159. }
  160. flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue);
  161. }
  162. }
  163. return flexspiDllValue;
  164. }
  165. status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status)
  166. {
  167. status_t result = kStatus_Success;
  168. /* Check for error. */
  169. status &= kErrorFlags;
  170. if (status)
  171. {
  172. /* Select the correct error code.. */
  173. if (status & kFLEXSPI_SequenceExecutionTimeoutFlag)
  174. {
  175. result = kStatus_FLEXSPI_SequenceExecutionTimeout;
  176. }
  177. else if (status & kFLEXSPI_IpCommandSequenceErrorFlag)
  178. {
  179. result = kStatus_FLEXSPI_IpCommandSequenceError;
  180. }
  181. else if (status & kFLEXSPI_IpCommandGrantTimeoutFlag)
  182. {
  183. result = kStatus_FLEXSPI_IpCommandGrantTimeout;
  184. }
  185. else
  186. {
  187. assert(false);
  188. }
  189. /* Clear the flags. */
  190. FLEXSPI_ClearInterruptStatusFlags(base, status);
  191. /* Reset fifos. These flags clear automatically. */
  192. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  193. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  194. }
  195. return result;
  196. }
  197. void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
  198. {
  199. uint32_t configValue = 0;
  200. uint8_t i = 0;
  201. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  202. /* Enable the flexspi clock */
  203. CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
  204. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  205. /* Reset peripheral before configuring it. */
  206. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  207. FLEXSPI_SoftwareReset(base);
  208. /* Configure MCR0 configuration items. */
  209. configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) |
  210. FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) |
  211. FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) |
  212. FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) |
  213. FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) |
  214. FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
  215. FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
  216. FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) | FLEXSPI_MCR0_MDIS_MASK;
  217. base->MCR0 = configValue;
  218. /* Configure MCR1 configurations. */
  219. configValue =
  220. FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle);
  221. base->MCR1 = configValue;
  222. /* Configure MCR2 configurations. */
  223. configValue = FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
  224. FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
  225. FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
  226. FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
  227. base->MCR2 = configValue;
  228. /* Configure AHB control items. */
  229. base->AHBCR = FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
  230. FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
  231. FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
  232. /* Configure AHB rx buffers. */
  233. for (i = 0; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1; i++)
  234. {
  235. base->AHBRXBUFCR0[i] = FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
  236. FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
  237. FLEXSPI_AHBRXBUFCR0_BUFSZ(config->ahbConfig.buffer[i].bufferSize / 8);
  238. }
  239. /* Configure IP Fifo watermarks. */
  240. base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK(config->rxWatermark / 8 - 1);
  241. base->IPTXFCR |= FLEXSPI_IPRXFCR_RXWMRK(config->txWatermark / 8 - 1);
  242. }
  243. void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
  244. {
  245. config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
  246. config->enableSckFreeRunning = false;
  247. config->enableCombination = false;
  248. config->enableDoze = true;
  249. config->enableHalfSpeedAccess = false;
  250. config->enableSckBDiffOpt = false;
  251. config->enableSameConfigForAll = false;
  252. config->seqTimeoutCycle = 0xFFFFU;
  253. config->ipGrantTimeoutCycle = 0xFFU;
  254. config->txWatermark = 8;
  255. config->rxWatermark = 8;
  256. config->ahbConfig.enableAHBWriteIpTxFifo = false;
  257. config->ahbConfig.enableAHBWriteIpRxFifo = false;
  258. config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
  259. config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU;
  260. config->ahbConfig.resumeWaitCycle = 0x20U;
  261. memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
  262. config->ahbConfig.enableClearAHBBufferOpt = false;
  263. config->ahbConfig.enableAHBPrefetch = false;
  264. config->ahbConfig.enableAHBBufferable = false;
  265. config->ahbConfig.enableAHBCachable = false;
  266. }
  267. void FLEXSPI_Deinit(FLEXSPI_Type *base)
  268. {
  269. /* Reset peripheral. */
  270. FLEXSPI_SoftwareReset(base);
  271. }
  272. void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
  273. {
  274. uint32_t configValue = 0;
  275. uint8_t index = port >> 1; /* PortA with index 0, PortB with index 1. */
  276. /* Wait for bus idle before change flash configuration. */
  277. while (!FLEXSPI_GetBusIdleStatus(base))
  278. {
  279. }
  280. /* Configure flash size. */
  281. base->FLSHCR0[index] = 0;
  282. base->FLSHCR0[port] = config->flashSize;
  283. /* Configure flash parameters. */
  284. base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
  285. FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
  286. FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
  287. FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
  288. /* Configure AHB operation items. */
  289. configValue = base->FLSHCR2[port];
  290. configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
  291. FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_AWRSEQID_MASK);
  292. configValue |=
  293. FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
  294. if (config->AWRSeqNumber > 0U)
  295. {
  296. configValue |=
  297. FLEXSPI_FLSHCR2_AWRSEQID(config->AWRSeqIndex) | FLEXSPI_FLSHCR2_AWRSEQNUM(config->AWRSeqNumber - 1U);
  298. }
  299. if (config->ARDSeqNumber > 0U)
  300. {
  301. configValue |=
  302. FLEXSPI_FLSHCR2_ARDSEQID(config->ARDSeqIndex) | FLEXSPI_FLSHCR2_ARDSEQNUM(config->ARDSeqNumber - 1U);
  303. }
  304. base->FLSHCR2[port] = configValue;
  305. /* Configure DLL. */
  306. base->DLLCR[index] = FLEXSPI_ConfigureDll(base, config);
  307. /* Configure write mask. */
  308. if (index == 0) /*PortA*/
  309. {
  310. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
  311. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
  312. }
  313. else
  314. {
  315. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
  316. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
  317. }
  318. /* Exit stop mode. */
  319. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  320. }
  321. void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
  322. {
  323. assert(index < 64U);
  324. uint8_t i = 0;
  325. volatile uint32_t *lutBase;
  326. /* Wait for bus idle before change flash configuration. */
  327. while (!FLEXSPI_GetBusIdleStatus(base))
  328. {
  329. }
  330. /* Unlock LUT for update. */
  331. base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
  332. base->LUTCR = 0x02;
  333. lutBase = &base->LUT[index];
  334. for (i = index; i < count; i++)
  335. {
  336. *lutBase++ = *cmd++;
  337. }
  338. /* Lock LUT. */
  339. base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
  340. base->LUTCR = 0x01;
  341. }
  342. status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
  343. {
  344. uint8_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1;
  345. uint32_t status;
  346. status_t result = kStatus_Success;
  347. uint32_t i = 0;
  348. /* Send data buffer */
  349. while (size)
  350. {
  351. /* Wait until there is room in the fifo. This also checks for errors. */
  352. while (!((status = base->INTR) & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag))
  353. {
  354. }
  355. result = FLEXSPI_CheckAndClearError(base, status);
  356. if (result)
  357. {
  358. return result;
  359. }
  360. /* Write watermark level data into tx fifo . */
  361. if (size >= 8 * txWatermark)
  362. {
  363. for (i = 0; i < 2 * txWatermark; i++)
  364. {
  365. base->TFDR[i] = *buffer++;
  366. }
  367. size = size - 8 * txWatermark;
  368. }
  369. else
  370. {
  371. for (i = 0; i < (size / 4 + 1); i++)
  372. {
  373. base->TFDR[i] = *buffer++;
  374. }
  375. size = 0;
  376. }
  377. /* Push a watermark level datas into IP TX FIFO. */
  378. base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag;
  379. }
  380. return result;
  381. }
  382. status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
  383. {
  384. uint8_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1;
  385. uint32_t status;
  386. status_t result = kStatus_Success;
  387. uint32_t i = 0;
  388. /* Send data buffer */
  389. while (size)
  390. {
  391. if (size >= 8 * rxWatermark)
  392. {
  393. /* Wait until there is room in the fifo. This also checks for errors. */
  394. while (!((status = base->INTR) & kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
  395. {
  396. result = FLEXSPI_CheckAndClearError(base, status);
  397. if (result)
  398. {
  399. return result;
  400. }
  401. }
  402. }
  403. else
  404. {
  405. /* Wait fill level. This also checks for errors. */
  406. while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U))
  407. {
  408. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  409. if (result)
  410. {
  411. return result;
  412. }
  413. }
  414. }
  415. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  416. if (result)
  417. {
  418. return result;
  419. }
  420. /* Read watermark level data from rx fifo . */
  421. if (size >= 8 * rxWatermark)
  422. {
  423. for (i = 0; i < 2 * rxWatermark; i++)
  424. {
  425. *buffer++ = base->RFDR[i];
  426. }
  427. size = size - 8 * rxWatermark;
  428. }
  429. else
  430. {
  431. for (i = 0; i < (size / 4 + 1); i++)
  432. {
  433. *buffer++ = base->RFDR[i];
  434. }
  435. size = 0;
  436. }
  437. /* Pop out a watermark level datas from IP RX FIFO. */
  438. base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
  439. }
  440. return result;
  441. }
  442. status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
  443. {
  444. uint32_t configValue = 0;
  445. status_t result = kStatus_Success;
  446. /* Clear sequence pointer before sending data to external devices. */
  447. base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
  448. /* Clear former pending status before start this tranfer. */
  449. base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
  450. FLEXSPI_INTR_IPCMDGE_MASK;
  451. /* Configure base addresss. */
  452. base->IPCR0 = xfer->deviceAddress;
  453. /* Reset fifos. */
  454. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  455. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  456. /* Configure data size. */
  457. if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
  458. {
  459. configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
  460. }
  461. /* Configure sequence ID. */
  462. configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1);
  463. base->IPCR1 = configValue;
  464. /* Start Transfer. */
  465. base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
  466. if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
  467. {
  468. result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
  469. }
  470. else if (xfer->cmdType == kFLEXSPI_Read)
  471. {
  472. result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
  473. }
  474. else
  475. {
  476. }
  477. /* Wait for bus idle. */
  478. while (!FLEXSPI_GetBusIdleStatus(base))
  479. {
  480. }
  481. if (xfer->cmdType == kFLEXSPI_Command)
  482. {
  483. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  484. }
  485. return result;
  486. }
  487. void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
  488. flexspi_handle_t *handle,
  489. flexspi_transfer_callback_t callback,
  490. void *userData)
  491. {
  492. assert(handle);
  493. uint32_t instance = FLEXSPI_GetInstance(base);
  494. /* Zero handle. */
  495. memset(handle, 0, sizeof(*handle));
  496. /* Set callback and userData. */
  497. handle->completionCallback = callback;
  498. handle->userData = userData;
  499. /* Save the context in global variables to support the double weak mechanism. */
  500. s_flexspiHandle[instance] = handle;
  501. /* Enable NVIC interrupt. */
  502. EnableIRQ(s_flexspiIrqs[instance]);
  503. }
  504. status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer)
  505. {
  506. uint32_t configValue = 0;
  507. status_t result = kStatus_Success;
  508. assert(handle);
  509. assert(xfer);
  510. /* Check if the I2C bus is idle - if not return busy status. */
  511. if (handle->state != kFLEXSPI_Idle)
  512. {
  513. result = kStatus_FLEXSPI_Busy;
  514. }
  515. else
  516. {
  517. handle->data = xfer->data;
  518. handle->dataSize = xfer->dataSize;
  519. handle->transferTotalSize = xfer->dataSize;
  520. handle->state = (xfer->cmdType == kFLEXSPI_Read) ? kFLEXSPI_BusyRead : kFLEXSPI_BusyWrite;
  521. /* Clear sequence pointer before sending data to external devices. */
  522. base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
  523. /* Clear former pending status before start this tranfer. */
  524. base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
  525. FLEXSPI_INTR_IPCMDGE_MASK;
  526. /* Configure base addresss. */
  527. base->IPCR0 = xfer->deviceAddress;
  528. /* Reset fifos. */
  529. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  530. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  531. /* Configure data size. */
  532. if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
  533. {
  534. configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
  535. }
  536. /* Configure sequence ID. */
  537. configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM(xfer->SeqNumber - 1);
  538. base->IPCR1 = configValue;
  539. /* Start Transfer. */
  540. base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
  541. if (handle->state == kFLEXSPI_BusyRead)
  542. {
  543. FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
  544. kFLEXSPI_SequenceExecutionTimeoutFlag |
  545. kFLEXSPI_IpCommandSequenceErrorFlag |
  546. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag);
  547. }
  548. else
  549. {
  550. FLEXSPI_EnableInterrupts(base, kFLEXSPI_IpTxFifoWatermarkEmpltyFlag |
  551. kFLEXSPI_SequenceExecutionTimeoutFlag |
  552. kFLEXSPI_IpCommandSequenceErrorFlag |
  553. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExcutionDoneFlag);
  554. }
  555. }
  556. return result;
  557. }
  558. status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
  559. {
  560. assert(handle);
  561. status_t result = kStatus_Success;
  562. if (handle->state == kFLEXSPI_Idle)
  563. {
  564. result = kStatus_NoTransferInProgress;
  565. }
  566. else
  567. {
  568. *count = handle->transferTotalSize - handle->dataSize;
  569. }
  570. return result;
  571. }
  572. void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
  573. {
  574. assert(handle);
  575. FLEXSPI_DisableInterrupts(base, kIrqFlags);
  576. handle->state = kFLEXSPI_Idle;
  577. }
  578. void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
  579. {
  580. uint8_t status;
  581. status_t result;
  582. uint8_t txWatermark;
  583. uint8_t rxWatermark;
  584. uint8_t i = 0;
  585. status = base->INTR;
  586. result = FLEXSPI_CheckAndClearError(base, status);
  587. if ((result != kStatus_Success) && (handle->completionCallback != NULL))
  588. {
  589. FLEXSPI_TransferAbort(base, handle);
  590. if (handle->completionCallback)
  591. {
  592. handle->completionCallback(base, handle, result, handle->userData);
  593. }
  594. return;
  595. }
  596. if ((status & kFLEXSPI_IpRxFifoWatermarkAvailableFlag) && (handle->state == kFLEXSPI_BusyRead))
  597. {
  598. rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1;
  599. /* Read watermark level data from rx fifo . */
  600. if (handle->dataSize >= 8 * rxWatermark)
  601. {
  602. /* Read watermark level data from rx fifo . */
  603. for (i = 0; i < 2 * rxWatermark; i++)
  604. {
  605. *handle->data++ = base->RFDR[i];
  606. }
  607. handle->dataSize = handle->dataSize - 8 * rxWatermark;
  608. }
  609. else
  610. {
  611. for (i = 0; i < (handle->dataSize / 4 + 1); i++)
  612. {
  613. *handle->data++ = base->RFDR[i];
  614. }
  615. handle->dataSize = 0;
  616. }
  617. /* Pop out a watermark level datas from IP RX FIFO. */
  618. base->INTR |= kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
  619. }
  620. if (status & kFLEXSPI_IpCommandExcutionDoneFlag)
  621. {
  622. base->INTR |= kFLEXSPI_IpCommandExcutionDoneFlag;
  623. FLEXSPI_TransferAbort(base, handle);
  624. if (handle->completionCallback)
  625. {
  626. handle->completionCallback(base, handle, kStatus_Success, handle->userData);
  627. }
  628. }
  629. /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
  630. if ((status & kFLEXSPI_IpTxFifoWatermarkEmpltyFlag) && (handle->state == kFLEXSPI_BusyWrite))
  631. {
  632. if (handle->dataSize)
  633. {
  634. txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1;
  635. /* Write watermark level data into tx fifo . */
  636. if (handle->dataSize >= 8 * txWatermark)
  637. {
  638. for (i = 0; i < 2 * txWatermark; i++)
  639. {
  640. base->TFDR[i] = *handle->data++;
  641. }
  642. handle->dataSize = handle->dataSize - 8 * txWatermark;
  643. }
  644. else
  645. {
  646. for (i = 0; i < (handle->dataSize / 4 + 1); i++)
  647. {
  648. base->TFDR[i] = *handle->data++;
  649. }
  650. handle->dataSize = 0;
  651. }
  652. /* Push a watermark level datas into IP TX FIFO. */
  653. base->INTR |= kFLEXSPI_IpTxFifoWatermarkEmpltyFlag;
  654. }
  655. }
  656. else
  657. {
  658. }
  659. }
  660. #if defined(FLEXSPI)
  661. void FLEXSPI_DriverIRQHandler(void)
  662. {
  663. FLEXSPI_TransferHandleIRQ(FLEXSPI, s_flexspiHandle[0]);
  664. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  665. exception return operation might vector to incorrect interrupt */
  666. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  667. __DSB();
  668. #endif
  669. }
  670. #endif
  671. #if defined(FLEXSPI0)
  672. void FLEXSPI0_DriverIRQHandler(void)
  673. {
  674. FLEXSPI_TransferHandleIRQ(FLEXSPI0, s_flexspiHandle[0]);
  675. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  676. exception return operation might vector to incorrect interrupt */
  677. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  678. __DSB();
  679. #endif
  680. }
  681. #endif
  682. #if defined(FLEXSPI1)
  683. void FLEXSPI1_DriverIRQHandler(void)
  684. {
  685. FLEXSPI_TransferHandleIRQ(FLEXSPI1, s_flexspiHandle[1]);
  686. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  687. exception return operation might vector to incorrect interrupt */
  688. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  689. __DSB();
  690. #endif
  691. }
  692. #endif