fsl_flexspi.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157
  1. /*
  2. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2021 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_flexspi.h"
  9. /* Component ID definition, used by tools. */
  10. #ifndef FSL_COMPONENT_ID
  11. #define FSL_COMPONENT_ID "platform.drivers.flexspi"
  12. #endif
  13. /*******************************************************************************
  14. * Definitions
  15. ******************************************************************************/
  16. #define FREQ_1MHz (1000000UL)
  17. #define FLEXSPI_DLLCR_DEFAULT (0x100UL)
  18. #define FLEXSPI_LUT_KEY_VAL (0x5AF05AF0UL)
  19. enum
  20. {
  21. kFLEXSPI_DelayCellUnitMin = 75, /* 75ps. */
  22. kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
  23. };
  24. enum
  25. {
  26. kFLEXSPI_FlashASampleClockSlaveDelayLocked =
  27. FLEXSPI_STS2_ASLVLOCK_MASK, /* Flash A sample clock slave delay line locked. */
  28. kFLEXSPI_FlashASampleClockRefDelayLocked =
  29. FLEXSPI_STS2_AREFLOCK_MASK, /* Flash A sample clock reference delay line locked. */
  30. kFLEXSPI_FlashBSampleClockSlaveDelayLocked =
  31. FLEXSPI_STS2_BSLVLOCK_MASK, /* Flash B sample clock slave delay line locked. */
  32. kFLEXSPI_FlashBSampleClockRefDelayLocked =
  33. FLEXSPI_STS2_BREFLOCK_MASK, /* Flash B sample clock reference delay line locked. */
  34. };
  35. /*! @brief Common sets of flags used by the driver, _flexspi_flag_constants. */
  36. enum
  37. {
  38. /*! IRQ sources enabled by the non-blocking transactional API. */
  39. kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmptyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
  40. kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
  41. kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExecutionDoneFlag,
  42. /*! Errors to check for. */
  43. kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
  44. kFLEXSPI_IpCommandGrantTimeoutFlag,
  45. };
  46. /* FLEXSPI transfer state, _flexspi_transfer_state. */
  47. enum
  48. {
  49. kFLEXSPI_Idle = 0x0U, /*!< Transfer is done. */
  50. kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */
  51. kFLEXSPI_BusyRead = 0x2U, /*!< FLEXSPI is busy write transfer. */
  52. };
  53. /*! @brief Typedef for interrupt handler. */
  54. typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, flexspi_handle_t *handle);
  55. /*******************************************************************************
  56. * Prototypes
  57. ******************************************************************************/
  58. static void FLEXSPI_Memset(void *src, uint8_t value, size_t length);
  59. /*!
  60. * @brief Calculate flash A/B sample clock DLL.
  61. *
  62. * @param base FLEXSPI base pointer.
  63. * @param config Flash configuration parameters.
  64. */
  65. static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
  66. /*******************************************************************************
  67. * Variables
  68. ******************************************************************************/
  69. /*! @brief Pointers to flexspi bases for each instance. */
  70. static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
  71. /*! @brief Pointers to flexspi IRQ number for each instance. */
  72. static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
  73. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  74. /* Clock name array */
  75. static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
  76. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  77. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  78. /*! @brief Pointers to flexspi handles for each instance. */
  79. static flexspi_handle_t *s_flexspiHandle[ARRAY_SIZE(s_flexspiBases)];
  80. #endif
  81. #if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
  82. /*! @brief Pointers to FLEXSPI resets for each instance. */
  83. static const reset_ip_name_t s_flexspiResets[] = FLEXSPI_RSTS;
  84. #endif
  85. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  86. /*! @brief Pointer to flexspi IRQ handler. */
  87. static flexspi_isr_t s_flexspiIsr;
  88. #endif
  89. /*******************************************************************************
  90. * Code
  91. ******************************************************************************/
  92. /* To avoid compiler opitimizing this API into memset() in library. */
  93. #if defined(__ICCARM__)
  94. #pragma optimize = none
  95. #endif /* defined(__ICCARM__) */
  96. static void FLEXSPI_Memset(void *src, uint8_t value, size_t length)
  97. {
  98. assert(src != NULL);
  99. uint8_t *p = src;
  100. for (uint32_t i = 0U; i < length; i++)
  101. {
  102. *p = value;
  103. p++;
  104. }
  105. }
  106. uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
  107. {
  108. uint32_t instance;
  109. /* Find the instance index from base address mappings. */
  110. for (instance = 0; instance < ARRAY_SIZE(s_flexspiBases); instance++)
  111. {
  112. if (s_flexspiBases[instance] == base)
  113. {
  114. break;
  115. }
  116. }
  117. assert(instance < ARRAY_SIZE(s_flexspiBases));
  118. return instance;
  119. }
  120. static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
  121. {
  122. bool isUnifiedConfig = true;
  123. uint32_t flexspiDllValue;
  124. uint32_t dllValue;
  125. uint32_t temp;
  126. #if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_PS) && FSL_FEATURE_FLEXSPI_DQS_DELAY_PS
  127. uint32_t internalDqsDelayPs = FSL_FEATURE_FLEXSPI_DQS_DELAY_PS;
  128. #endif
  129. uint32_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
  130. switch (rxSampleClock)
  131. {
  132. case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackInternally:
  133. case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
  134. case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
  135. isUnifiedConfig = true;
  136. break;
  137. case (uint32_t)kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
  138. if (config->isSck2Enabled)
  139. {
  140. isUnifiedConfig = true;
  141. }
  142. else
  143. {
  144. isUnifiedConfig = false;
  145. }
  146. break;
  147. default:
  148. assert(false);
  149. break;
  150. }
  151. if (isUnifiedConfig)
  152. {
  153. flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
  154. }
  155. else
  156. {
  157. if (config->flexspiRootClk >= 100U * FREQ_1MHz)
  158. {
  159. #if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN) && FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN
  160. /* DLLEN = 1, SLVDLYTARGET = 0x0, */
  161. flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x00);
  162. #else
  163. /* DLLEN = 1, SLVDLYTARGET = 0xF, */
  164. flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
  165. #endif
  166. }
  167. else
  168. {
  169. temp = (uint32_t)config->dataValidTime * 1000U; /* Convert data valid time in ns to ps. */
  170. dllValue = temp / (uint32_t)kFLEXSPI_DelayCellUnitMin;
  171. if (dllValue * (uint32_t)kFLEXSPI_DelayCellUnitMin < temp)
  172. {
  173. dllValue++;
  174. }
  175. flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue);
  176. }
  177. }
  178. return flexspiDllValue;
  179. }
  180. status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status)
  181. {
  182. status_t result = kStatus_Success;
  183. /* Check for error. */
  184. status &= (uint32_t)kErrorFlags;
  185. if (0U != status)
  186. {
  187. /* Select the correct error code.. */
  188. if (0U != (status & (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag))
  189. {
  190. result = kStatus_FLEXSPI_SequenceExecutionTimeout;
  191. }
  192. else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag))
  193. {
  194. result = kStatus_FLEXSPI_IpCommandSequenceError;
  195. }
  196. else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag))
  197. {
  198. result = kStatus_FLEXSPI_IpCommandGrantTimeout;
  199. }
  200. else
  201. {
  202. assert(false);
  203. }
  204. /* Clear the flags. */
  205. FLEXSPI_ClearInterruptStatusFlags(base, status);
  206. /* Reset fifos. These flags clear automatically. */
  207. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  208. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  209. }
  210. return result;
  211. }
  212. /*!
  213. * brief Initializes the FLEXSPI module and internal state.
  214. *
  215. * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the
  216. * input configure parameters. Users should call this function before any FLEXSPI operations.
  217. *
  218. * param base FLEXSPI peripheral base address.
  219. * param config FLEXSPI configure structure.
  220. */
  221. void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
  222. {
  223. uint32_t configValue = 0;
  224. uint8_t i = 0;
  225. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  226. /* Enable the flexspi clock */
  227. (void)CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
  228. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  229. #if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
  230. /* Reset the FLEXSPI module */
  231. RESET_PeripheralReset(s_flexspiResets[FLEXSPI_GetInstance(base)]);
  232. #endif
  233. /* Reset peripheral before configuring it. */
  234. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  235. FLEXSPI_SoftwareReset(base);
  236. /* Configure MCR0 configuration items. */
  237. configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) |
  238. FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) |
  239. FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) |
  240. FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) |
  241. FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) |
  242. #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
  243. FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
  244. #endif
  245. #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
  246. FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
  247. #endif
  248. #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
  249. FLEXSPI_MCR0_ARDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) |
  250. #endif
  251. FLEXSPI_MCR0_MDIS_MASK;
  252. base->MCR0 = configValue;
  253. /* Configure MCR1 configurations. */
  254. configValue =
  255. FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle);
  256. base->MCR1 = configValue;
  257. /* Configure MCR2 configurations. */
  258. configValue = base->MCR2;
  259. configValue &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK | FLEXSPI_MCR2_SCKBDIFFOPT_MASK | FLEXSPI_MCR2_SAMEDEVICEEN_MASK |
  260. FLEXSPI_MCR2_CLRAHBBUFOPT_MASK);
  261. configValue |= FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
  262. FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
  263. FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
  264. FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
  265. base->MCR2 = configValue;
  266. /* Configure AHB control items. */
  267. configValue = base->AHBCR;
  268. configValue &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_BUFFERABLEEN_MASK |
  269. FLEXSPI_AHBCR_CACHABLEEN_MASK);
  270. configValue |= FLEXSPI_AHBCR_READADDROPT(config->ahbConfig.enableReadAddressOpt) |
  271. FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
  272. FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
  273. FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
  274. base->AHBCR = configValue;
  275. /* Configure AHB rx buffers. */
  276. for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
  277. {
  278. configValue = base->AHBRXBUFCR0[i];
  279. configValue &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK |
  280. FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK);
  281. configValue |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN(config->ahbConfig.buffer[i].enablePrefetch) |
  282. FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
  283. FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
  284. FLEXSPI_AHBRXBUFCR0_BUFSZ((uint32_t)config->ahbConfig.buffer[i].bufferSize / 8U);
  285. base->AHBRXBUFCR0[i] = configValue;
  286. }
  287. /* Configure IP Fifo watermarks. */
  288. base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK;
  289. base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK((uint32_t)config->rxWatermark / 8U - 1U);
  290. base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK;
  291. base->IPTXFCR |= FLEXSPI_IPTXFCR_TXWMRK((uint32_t)config->txWatermark / 8U - 1U);
  292. /* Reset flash size on all ports */
  293. for (i = 0; i < (uint32_t)kFLEXSPI_PortCount; i++)
  294. {
  295. base->FLSHCR0[i] = 0;
  296. }
  297. }
  298. /*!
  299. * brief Gets default settings for FLEXSPI.
  300. *
  301. * param config FLEXSPI configuration structure.
  302. */
  303. void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
  304. {
  305. /* Initializes the configure structure to zero. */
  306. FLEXSPI_Memset(config, 0, sizeof(*config));
  307. config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
  308. config->enableSckFreeRunning = false;
  309. #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
  310. config->enableCombination = false;
  311. #endif
  312. config->enableDoze = true;
  313. config->enableHalfSpeedAccess = false;
  314. config->enableSckBDiffOpt = false;
  315. config->enableSameConfigForAll = false;
  316. config->seqTimeoutCycle = 0xFFFFU;
  317. config->ipGrantTimeoutCycle = 0xFFU;
  318. config->txWatermark = 8;
  319. config->rxWatermark = 8;
  320. #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
  321. config->ahbConfig.enableAHBWriteIpTxFifo = false;
  322. #endif
  323. #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
  324. config->ahbConfig.enableAHBWriteIpRxFifo = false;
  325. #endif
  326. config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
  327. config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU;
  328. config->ahbConfig.resumeWaitCycle = 0x20U;
  329. FLEXSPI_Memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
  330. /* Use invalid master ID 0xF and buffer size 0 for the first several buffers. */
  331. for (uint8_t i = 0; i < ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U); i++)
  332. {
  333. config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
  334. config->ahbConfig.buffer[i].masterIndex = 0xFU; /* Invalid master index which is not used, so will never hit. */
  335. config->ahbConfig.buffer[i].bufferSize =
  336. 0; /* Default buffer size 0 for buffer0 to buffer(FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 3U)*/
  337. }
  338. for (uint8_t i = ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U);
  339. i < (uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
  340. {
  341. config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
  342. config->ahbConfig.buffer[i].bufferSize = 256U; /* Default buffer size 256 bytes. */
  343. }
  344. config->ahbConfig.enableClearAHBBufferOpt = false;
  345. config->ahbConfig.enableReadAddressOpt = false;
  346. config->ahbConfig.enableAHBPrefetch = false;
  347. config->ahbConfig.enableAHBBufferable = false;
  348. config->ahbConfig.enableAHBCachable = false;
  349. }
  350. /*!
  351. * brief Deinitializes the FLEXSPI module.
  352. *
  353. * Clears the FLEXSPI state and FLEXSPI module registers.
  354. * param base FLEXSPI peripheral base address.
  355. */
  356. void FLEXSPI_Deinit(FLEXSPI_Type *base)
  357. {
  358. /* Reset peripheral. */
  359. FLEXSPI_SoftwareReset(base);
  360. }
  361. /*!
  362. * brief Update FLEXSPI DLL value depending on currently flexspi root clock.
  363. *
  364. * param base FLEXSPI peripheral base address.
  365. * param config Flash configuration parameters.
  366. * param port FLEXSPI Operation port.
  367. */
  368. void FLEXSPI_UpdateDllValue(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
  369. {
  370. uint32_t configValue = 0;
  371. uint32_t statusValue = 0;
  372. uint8_t index = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
  373. /* Wait for bus to be idle before changing flash configuration. */
  374. while (!FLEXSPI_GetBusIdleStatus(base))
  375. {
  376. }
  377. /* Configure DLL. */
  378. configValue = FLEXSPI_CalculateDll(base, config);
  379. base->DLLCR[index] = configValue;
  380. /* Exit stop mode. */
  381. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  382. /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */
  383. statusValue =
  384. (index == 0U) ?
  385. ((uint32_t)kFLEXSPI_FlashASampleClockSlaveDelayLocked |
  386. (uint32_t)kFLEXSPI_FlashASampleClockRefDelayLocked) :
  387. ((uint32_t)kFLEXSPI_FlashBSampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashBSampleClockRefDelayLocked);
  388. if (0U != (configValue & FLEXSPI_DLLCR_DLLEN_MASK))
  389. {
  390. /* Wait slave delay line locked and slave reference delay line locked. */
  391. while ((base->STS2 & statusValue) != statusValue)
  392. {
  393. }
  394. /* Wait at least 100 NOPs*/
  395. for (uint8_t delay = 100U; delay > 0U; delay--)
  396. {
  397. __NOP();
  398. }
  399. }
  400. }
  401. /*!
  402. * brief Configures the connected device parameter.
  403. *
  404. * This function configures the connected device relevant parameters, such as the size, command, and so on.
  405. * The flash configuration value cannot have a default value. The user needs to configure it according to the
  406. * connected device.
  407. *
  408. * param base FLEXSPI peripheral base address.
  409. * param config Flash configuration parameters.
  410. * param port FLEXSPI Operation port.
  411. */
  412. void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
  413. {
  414. uint32_t configValue = 0;
  415. uint8_t index = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
  416. /* Wait for bus to be idle before changing flash configuration. */
  417. while (!FLEXSPI_GetBusIdleStatus(base))
  418. {
  419. }
  420. /* Configure flash size. */
  421. base->FLSHCR0[port] = config->flashSize;
  422. /* Configure flash parameters. */
  423. base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
  424. FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
  425. FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
  426. FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
  427. /* Configure AHB operation items. */
  428. configValue = base->FLSHCR2[port];
  429. configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
  430. FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_ARDSEQID_MASK);
  431. configValue |=
  432. FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
  433. if (config->AWRSeqNumber > 0U)
  434. {
  435. configValue |= FLEXSPI_FLSHCR2_AWRSEQID((uint32_t)config->AWRSeqIndex) |
  436. FLEXSPI_FLSHCR2_AWRSEQNUM((uint32_t)config->AWRSeqNumber - 1U);
  437. }
  438. if (config->ARDSeqNumber > 0U)
  439. {
  440. configValue |= FLEXSPI_FLSHCR2_ARDSEQID((uint32_t)config->ARDSeqIndex) |
  441. FLEXSPI_FLSHCR2_ARDSEQNUM((uint32_t)config->ARDSeqNumber - 1U);
  442. }
  443. base->FLSHCR2[port] = configValue;
  444. /* Configure DLL. */
  445. FLEXSPI_UpdateDllValue(base, config, port);
  446. /* Step into stop mode. */
  447. base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
  448. /* Configure write mask. */
  449. if (config->enableWriteMask)
  450. {
  451. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK;
  452. }
  453. else
  454. {
  455. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK;
  456. }
  457. if (index == 0U) /*PortA*/
  458. {
  459. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
  460. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
  461. }
  462. else
  463. {
  464. base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
  465. base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
  466. }
  467. /* Exit stop mode. */
  468. base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
  469. /* Wait for bus to be idle before use it access to external flash. */
  470. while (!FLEXSPI_GetBusIdleStatus(base))
  471. {
  472. }
  473. }
  474. /*! brief Updates the LUT table.
  475. *
  476. * param base FLEXSPI peripheral base address.
  477. * param index From which index start to update. It could be any index of the LUT table, which
  478. * also allows user to update command content inside a command. Each command consists of up to
  479. * 8 instructions and occupy 4*32-bit memory.
  480. * param cmd Command sequence array.
  481. * param count Number of sequences.
  482. */
  483. void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
  484. {
  485. assert(index < 64U);
  486. uint32_t i = 0;
  487. volatile uint32_t *lutBase;
  488. /* Wait for bus to be idle before changing flash configuration. */
  489. while (!FLEXSPI_GetBusIdleStatus(base))
  490. {
  491. }
  492. /* Unlock LUT for update. */
  493. base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
  494. base->LUTCR = 0x02;
  495. lutBase = &base->LUT[index];
  496. for (i = 0; i < count; i++)
  497. {
  498. *lutBase++ = *cmd++;
  499. }
  500. /* Lock LUT. */
  501. base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
  502. base->LUTCR = 0x01;
  503. }
  504. /*! brief Update read sample clock source
  505. *
  506. * param base FLEXSPI peripheral base address.
  507. * param clockSource clockSource of type #flexspi_read_sample_clock_t
  508. */
  509. void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource)
  510. {
  511. uint32_t mcr0Val;
  512. /* Wait for bus to be idle before changing flash configuration. */
  513. while (!FLEXSPI_GetBusIdleStatus(base))
  514. {
  515. }
  516. mcr0Val = base->MCR0;
  517. mcr0Val &= ~FLEXSPI_MCR0_RXCLKSRC_MASK;
  518. mcr0Val |= FLEXSPI_MCR0_RXCLKSRC(clockSource);
  519. base->MCR0 = mcr0Val;
  520. /* Reset peripheral. */
  521. FLEXSPI_SoftwareReset(base);
  522. }
  523. /*!
  524. * brief Sends a buffer of data bytes using blocking method.
  525. * note This function blocks via polling until all bytes have been sent.
  526. * param base FLEXSPI peripheral base address
  527. * param buffer The data bytes to send
  528. * param size The number of data bytes to send
  529. * retval kStatus_Success write success without error
  530. * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
  531. * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
  532. * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
  533. */
  534. status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
  535. {
  536. uint32_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
  537. uint32_t status;
  538. status_t result = kStatus_Success;
  539. uint32_t i = 0;
  540. /* Send data buffer */
  541. while (0U != size)
  542. {
  543. /* Wait until there is room in the fifo. This also checks for errors. */
  544. while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag))
  545. {
  546. }
  547. result = FLEXSPI_CheckAndClearError(base, status);
  548. if (kStatus_Success != result)
  549. {
  550. return result;
  551. }
  552. /* Write watermark level data into tx fifo . */
  553. if (size >= 8U * txWatermark)
  554. {
  555. for (i = 0U; i < 2U * txWatermark; i++)
  556. {
  557. base->TFDR[i] = *buffer++;
  558. }
  559. size = size - 8U * txWatermark;
  560. }
  561. else
  562. {
  563. for (i = 0U; i < ((size + 3U) / 4U); i++)
  564. {
  565. base->TFDR[i] = *buffer++;
  566. }
  567. size = 0U;
  568. }
  569. /* Push a watermark level data into IP TX FIFO. */
  570. base->INTR |= (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
  571. }
  572. return result;
  573. }
  574. /*!
  575. * brief Receives a buffer of data bytes using a blocking method.
  576. * note This function blocks via polling until all bytes have been sent.
  577. * param base FLEXSPI peripheral base address
  578. * param buffer The data bytes to send
  579. * param size The number of data bytes to receive
  580. * retval kStatus_Success read success without error
  581. * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
  582. * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
  583. * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
  584. */
  585. status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint32_t *buffer, size_t size)
  586. {
  587. uint32_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
  588. uint32_t status;
  589. status_t result = kStatus_Success;
  590. uint32_t i = 0;
  591. bool isReturn = false;
  592. /* Send data buffer */
  593. while (0U != size)
  594. {
  595. if (size >= 8U * rxWatermark)
  596. {
  597. /* Wait until there is room in the fifo. This also checks for errors. */
  598. while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
  599. {
  600. result = FLEXSPI_CheckAndClearError(base, status);
  601. if (kStatus_Success != result)
  602. {
  603. isReturn = true;
  604. break;
  605. }
  606. }
  607. }
  608. else
  609. {
  610. /* Wait fill level. This also checks for errors. */
  611. while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U))
  612. {
  613. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  614. if (kStatus_Success != result)
  615. {
  616. isReturn = true;
  617. break;
  618. }
  619. }
  620. }
  621. if (isReturn)
  622. {
  623. break;
  624. }
  625. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  626. if (kStatus_Success != result)
  627. {
  628. break;
  629. }
  630. /* Read watermark level data from rx fifo . */
  631. if (size >= 8U * rxWatermark)
  632. {
  633. for (i = 0U; i < 2U * rxWatermark; i++)
  634. {
  635. *buffer++ = base->RFDR[i];
  636. }
  637. size = size - 8U * rxWatermark;
  638. }
  639. else
  640. {
  641. for (i = 0U; i < ((size + 3U) / 4U); i++)
  642. {
  643. *buffer++ = base->RFDR[i];
  644. }
  645. size = 0;
  646. }
  647. /* Pop out a watermark level datas from IP RX FIFO. */
  648. base->INTR |= (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
  649. }
  650. return result;
  651. }
  652. /*!
  653. * brief Execute command to transfer a buffer data bytes using a blocking method.
  654. * param base FLEXSPI peripheral base address
  655. * param xfer pointer to the transfer structure.
  656. * retval kStatus_Success command transfer success without error
  657. * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
  658. * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
  659. * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
  660. */
  661. status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
  662. {
  663. uint32_t configValue = 0;
  664. status_t result = kStatus_Success;
  665. /* Clear sequence pointer before sending data to external devices. */
  666. base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
  667. /* Clear former pending status before start this transfer. */
  668. base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
  669. FLEXSPI_INTR_IPCMDGE_MASK;
  670. /* Configure base address. */
  671. base->IPCR0 = xfer->deviceAddress;
  672. /* Reset fifos. */
  673. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  674. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  675. /* Configure data size. */
  676. if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
  677. {
  678. configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
  679. }
  680. /* Configure sequence ID. */
  681. configValue |=
  682. FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
  683. base->IPCR1 = configValue;
  684. /* Start Transfer. */
  685. base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
  686. if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
  687. {
  688. result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
  689. }
  690. else if (xfer->cmdType == kFLEXSPI_Read)
  691. {
  692. result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
  693. }
  694. else
  695. {
  696. /* Empty else. */
  697. }
  698. /* Wait for bus to be idle before changing flash configuration. */
  699. while (!FLEXSPI_GetBusIdleStatus(base))
  700. {
  701. }
  702. if (xfer->cmdType == kFLEXSPI_Command)
  703. {
  704. result = FLEXSPI_CheckAndClearError(base, base->INTR);
  705. }
  706. return result;
  707. }
  708. /*!
  709. * brief Initializes the FLEXSPI handle which is used in transactional functions.
  710. *
  711. * param base FLEXSPI peripheral base address.
  712. * param handle pointer to flexspi_handle_t structure to store the transfer state.
  713. * param callback pointer to user callback function.
  714. * param userData user parameter passed to the callback function.
  715. */
  716. void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
  717. flexspi_handle_t *handle,
  718. flexspi_transfer_callback_t callback,
  719. void *userData)
  720. {
  721. assert(NULL != handle);
  722. uint32_t instance = FLEXSPI_GetInstance(base);
  723. /* Zero handle. */
  724. (void)memset(handle, 0, sizeof(*handle));
  725. /* Set callback and userData. */
  726. handle->completionCallback = callback;
  727. handle->userData = userData;
  728. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  729. /* Save the context in global variables to support the double weak mechanism. */
  730. s_flexspiHandle[instance] = handle;
  731. s_flexspiIsr = FLEXSPI_TransferHandleIRQ;
  732. #endif
  733. /* Enable NVIC interrupt. */
  734. (void)EnableIRQ(s_flexspiIrqs[instance]);
  735. }
  736. /*!
  737. * brief Performs a interrupt non-blocking transfer on the FLEXSPI bus.
  738. *
  739. * note Calling the API returns immediately after transfer initiates. The user needs
  740. * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether
  741. * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer
  742. * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark level, or
  743. * FLEXSPI could not read data properly.
  744. *
  745. * param base FLEXSPI peripheral base address.
  746. * param handle pointer to flexspi_handle_t structure which stores the transfer state.
  747. * param xfer pointer to flexspi_transfer_t structure.
  748. * retval kStatus_Success Successfully start the data transmission.
  749. * retval kStatus_FLEXSPI_Busy Previous transmission still not finished.
  750. */
  751. status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer)
  752. {
  753. uint32_t configValue = 0;
  754. status_t result = kStatus_Success;
  755. assert(NULL != handle);
  756. assert(NULL != xfer);
  757. /* Check if the I2C bus is idle - if not return busy status. */
  758. if (handle->state != (uint32_t)kFLEXSPI_Idle)
  759. {
  760. result = kStatus_FLEXSPI_Busy;
  761. }
  762. else
  763. {
  764. handle->data = xfer->data;
  765. handle->dataSize = xfer->dataSize;
  766. handle->transferTotalSize = xfer->dataSize;
  767. handle->state = (xfer->cmdType == kFLEXSPI_Read) ? (uint32_t)kFLEXSPI_BusyRead : (uint32_t)kFLEXSPI_BusyWrite;
  768. /* Clear sequence pointer before sending data to external devices. */
  769. base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
  770. /* Clear former pending status before start this transfer. */
  771. base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
  772. FLEXSPI_INTR_IPCMDGE_MASK;
  773. /* Configure base address. */
  774. base->IPCR0 = xfer->deviceAddress;
  775. /* Reset fifos. */
  776. base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
  777. base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
  778. /* Configure data size. */
  779. if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
  780. {
  781. configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
  782. }
  783. /* Configure sequence ID. */
  784. configValue |=
  785. FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
  786. base->IPCR1 = configValue;
  787. /* Start Transfer. */
  788. base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
  789. if (handle->state == (uint32_t)kFLEXSPI_BusyRead)
  790. {
  791. FLEXSPI_EnableInterrupts(base, (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
  792. (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
  793. (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag |
  794. (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
  795. (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
  796. }
  797. else
  798. {
  799. FLEXSPI_EnableInterrupts(
  800. base, (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag | (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
  801. (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag | (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
  802. (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
  803. }
  804. }
  805. return result;
  806. }
  807. /*!
  808. * brief Gets the master transfer status during a interrupt non-blocking transfer.
  809. *
  810. * param base FLEXSPI peripheral base address.
  811. * param handle pointer to flexspi_handle_t structure which stores the transfer state.
  812. * param count Number of bytes transferred so far by the non-blocking transaction.
  813. * retval kStatus_InvalidArgument count is Invalid.
  814. * retval kStatus_Success Successfully return the count.
  815. */
  816. status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
  817. {
  818. assert(NULL != handle);
  819. status_t result = kStatus_Success;
  820. if (handle->state == (uint32_t)kFLEXSPI_Idle)
  821. {
  822. result = kStatus_NoTransferInProgress;
  823. }
  824. else
  825. {
  826. *count = handle->transferTotalSize - handle->dataSize;
  827. }
  828. return result;
  829. }
  830. /*!
  831. * brief Aborts an interrupt non-blocking transfer early.
  832. *
  833. * note This API can be called at any time when an interrupt non-blocking transfer initiates
  834. * to abort the transfer early.
  835. *
  836. * param base FLEXSPI peripheral base address.
  837. * param handle pointer to flexspi_handle_t structure which stores the transfer state
  838. */
  839. void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
  840. {
  841. assert(NULL != handle);
  842. FLEXSPI_DisableInterrupts(base, (uint32_t)kIrqFlags);
  843. handle->state = (uint32_t)kFLEXSPI_Idle;
  844. }
  845. /*!
  846. * brief Master interrupt handler.
  847. *
  848. * param base FLEXSPI peripheral base address.
  849. * param handle pointer to flexspi_handle_t structure.
  850. */
  851. void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
  852. {
  853. uint32_t status;
  854. status_t result;
  855. uint32_t intEnableStatus;
  856. uint32_t txWatermark;
  857. uint32_t rxWatermark;
  858. uint8_t i = 0;
  859. status = base->INTR;
  860. intEnableStatus = base->INTEN;
  861. /* Check if interrupt is enabled and status is alerted. */
  862. if ((status & intEnableStatus) != 0U)
  863. {
  864. result = FLEXSPI_CheckAndClearError(base, status);
  865. if ((result != kStatus_Success) && (handle->completionCallback != NULL))
  866. {
  867. FLEXSPI_TransferAbort(base, handle);
  868. if (NULL != handle->completionCallback)
  869. {
  870. handle->completionCallback(base, handle, result, handle->userData);
  871. }
  872. }
  873. else
  874. {
  875. if ((0U != (status & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag)) &&
  876. (handle->state == (uint32_t)kFLEXSPI_BusyRead))
  877. {
  878. rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
  879. /* Read watermark level data from rx fifo . */
  880. if (handle->dataSize >= 8U * rxWatermark)
  881. {
  882. /* Read watermark level data from rx fifo . */
  883. for (i = 0U; i < 2U * rxWatermark; i++)
  884. {
  885. *handle->data++ = base->RFDR[i];
  886. }
  887. handle->dataSize = handle->dataSize - 8U * rxWatermark;
  888. }
  889. else
  890. {
  891. for (i = 0; i < (handle->dataSize + 3U) / 4U; i++)
  892. {
  893. *handle->data++ = base->RFDR[i];
  894. }
  895. handle->dataSize = 0;
  896. }
  897. /* Pop out a watermark level data from IP RX FIFO. */
  898. base->INTR |= (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
  899. }
  900. if (0U != (status & (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag))
  901. {
  902. base->INTR |= (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag;
  903. FLEXSPI_TransferAbort(base, handle);
  904. if (NULL != handle->completionCallback)
  905. {
  906. handle->completionCallback(base, handle, kStatus_Success, handle->userData);
  907. }
  908. }
  909. /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
  910. if ((0U != (status & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag)) &&
  911. (handle->state == (uint32_t)kFLEXSPI_BusyWrite))
  912. {
  913. if (0U != handle->dataSize)
  914. {
  915. txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
  916. /* Write watermark level data into tx fifo . */
  917. if (handle->dataSize >= 8U * txWatermark)
  918. {
  919. for (i = 0; i < 2U * txWatermark; i++)
  920. {
  921. base->TFDR[i] = *handle->data++;
  922. }
  923. handle->dataSize = handle->dataSize - 8U * txWatermark;
  924. }
  925. else
  926. {
  927. for (i = 0; i < (handle->dataSize + 3U) / 4U; i++)
  928. {
  929. base->TFDR[i] = *handle->data++;
  930. }
  931. handle->dataSize = 0;
  932. }
  933. /* Push a watermark level data into IP TX FIFO. */
  934. base->INTR |= (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
  935. }
  936. }
  937. else
  938. {
  939. /* Empty else */
  940. }
  941. }
  942. }
  943. else
  944. {
  945. /* Empty else */
  946. }
  947. }
  948. #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
  949. #if defined(FLEXSPI)
  950. void FLEXSPI_DriverIRQHandler(void);
  951. void FLEXSPI_DriverIRQHandler(void)
  952. {
  953. s_flexspiIsr(FLEXSPI, s_flexspiHandle[0]);
  954. SDK_ISR_EXIT_BARRIER;
  955. }
  956. #endif
  957. #if defined(FLEXSPI0)
  958. void FLEXSPI0_DriverIRQHandler(void);
  959. void FLEXSPI0_DriverIRQHandler(void)
  960. {
  961. s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
  962. SDK_ISR_EXIT_BARRIER;
  963. }
  964. #endif
  965. #if defined(FLEXSPI1)
  966. void FLEXSPI1_DriverIRQHandler(void);
  967. void FLEXSPI1_DriverIRQHandler(void)
  968. {
  969. s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
  970. SDK_ISR_EXIT_BARRIER;
  971. }
  972. #endif
  973. #if defined(LSIO__FLEXSPI0)
  974. void LSIO_OCTASPI0_INT_DriverIRQHandler(void);
  975. void LSIO_OCTASPI0_INT_DriverIRQHandler(void)
  976. {
  977. s_flexspiIsr(LSIO__FLEXSPI0, s_flexspiHandle[0]);
  978. SDK_ISR_EXIT_BARRIER;
  979. }
  980. #endif
  981. #if defined(LSIO__FLEXSPI1)
  982. void LSIO_OCTASPI1_INT_DriverIRQHandler(void);
  983. void LSIO_OCTASPI1_INT_DriverIRQHandler(void)
  984. {
  985. s_flexspiIsr(LSIO__FLEXSPI1, s_flexspiHandle[1]);
  986. SDK_ISR_EXIT_BARRIER;
  987. }
  988. #endif
  989. #if defined(FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1
  990. void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void);
  991. void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void)
  992. {
  993. /* If handle is registered, treat the transfer function is enabled. */
  994. if (NULL != s_flexspiHandle[0])
  995. {
  996. s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
  997. }
  998. if (NULL != s_flexspiHandle[1])
  999. {
  1000. s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
  1001. }
  1002. }
  1003. #endif
  1004. #endif