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