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