1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_qspi.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.qspi"
14 #endif
15
16 /*******************************************************************************
17 * Definitations
18 ******************************************************************************/
19 enum _qspi_transfer_state
20 {
21 kQSPI_TxBusy = 0x0U, /*!< QSPI is busy */
22 kQSPI_TxIdle, /*!< Transfer is done. */
23 kQSPI_TxError /*!< Transfer error occurred. */
24 };
25
26 #define QSPI_AHB_BUFFER_REG(base, index) (((volatile uint32_t *)&((base)->BUF0CR))[(index)])
27
28 #if (!defined(FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG)) || !FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG
29 #ifndef QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK
30 #define QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK (0x100U)
31 #endif
32
33 #ifndef QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK
34 #define QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK (0x200U)
35 #endif
36
37 #ifndef QuadSPI_SOCCR_DQS_PHASE_SEL_MASK
38 #define QuadSPI_SOCCR_DQS_PHASE_SEL_MASK (0xC00U)
39 #define QuadSPI_SOCCR_DQS_PHASE_SEL_SHIFT (10U)
40 #define QuadSPI_SOCCR_DQS_PHASE_SEL(x) \
41 (((uint32_t)(((uint32_t)(x)) << QuadSPI_SOCCR_DQS_PHASE_SEL_SHIFT)) & QuadSPI_SOCCR_DQS_PHASE_SEL_MASK)
42 #endif
43
44 #ifndef QuadSPI_SOCCR_DQS_INV_EN_MASK
45 #define QuadSPI_SOCCR_DQS_INV_EN_MASK (0x1000U)
46 #define QuadSPI_SOCCR_DQS_INV_EN_SHIFT (12U)
47 #define QuadSPI_SOCCR_DQS_INV_EN(x) \
48 (((uint32_t)(((uint32_t)(x)) << QuadSPI_SOCCR_DQS_INV_EN_SHIFT)) & QuadSPI_SOCCR_DQS_INV_EN_MASK)
49 #endif
50
51 #ifndef QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK
52 #define QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK (0x7F0000U)
53 #define QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_SHIFT (16U)
54 #define QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL(x) \
55 (((uint32_t)(((uint32_t)(x)) << QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_SHIFT)) & \
56 QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK)
57 #endif
58 #endif /* FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG */
59
60 /*******************************************************************************
61 * Prototypes
62 ******************************************************************************/
63
64 /*******************************************************************************
65 * Variables
66 ******************************************************************************/
67 /* Base pointer array */
68 static QuadSPI_Type *const s_qspiBases[] = QuadSPI_BASE_PTRS;
69 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
70 /* Clock name array */
71 static const clock_ip_name_t s_qspiClock[] = QSPI_CLOCKS;
72 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
73
74 /*******************************************************************************
75 * Code
76 ******************************************************************************/
77 /*!
78 * brief Get the instance number for QSPI.
79 *
80 * param base QSPI base pointer.
81 */
QSPI_GetInstance(QuadSPI_Type * base)82 uint32_t QSPI_GetInstance(QuadSPI_Type *base)
83 {
84 uint32_t instance;
85
86 /* Find the instance index from base address mappings. */
87 for (instance = 0; instance < ARRAY_SIZE(s_qspiBases); instance++)
88 {
89 if (s_qspiBases[instance] == base)
90 {
91 break;
92 }
93 }
94
95 assert(instance < ARRAY_SIZE(s_qspiBases));
96
97 return instance;
98 }
99
100 /*!
101 * brief Initializes the QSPI module and internal state.
102 *
103 * This function enables the clock for QSPI and also configures the QSPI with the
104 * input configure parameters. Users should call this function before any QSPI operations.
105 *
106 * param base Pointer to QuadSPI Type.
107 * param config QSPI configure structure.
108 * param srcClock_Hz QSPI source clock frequency in Hz.
109 */
QSPI_Init(QuadSPI_Type * base,qspi_config_t * config,uint32_t srcClock_Hz)110 void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz)
111 {
112 uint32_t i = 0;
113 uint32_t val = 0;
114
115 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
116 /* Enable QSPI clock */
117 CLOCK_EnableClock(s_qspiClock[QSPI_GetInstance(base)]);
118 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
119
120 /* Do software reset to QSPI module */
121 QSPI_SoftwareReset(base);
122
123 /* Clear the FIFO region */
124 QSPI_ClearFifo(base, (uint32_t)kQSPI_AllFifo);
125
126 /* Configure QSPI */
127 QSPI_Enable(base, false);
128
129 #if !defined(FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL) || (!FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL)
130 /* Set qspi clock source */
131 base->SOCCR = config->clockSource;
132
133 /* Read MCR value, mask SCLKCFG field */
134 val = base->MCR;
135 val &= ~QuadSPI_MCR_SCLKCFG_MASK;
136
137 /* To avoid the configured baudrate exceeds the expected baudrate value, which may possibly put the
138 QSPI work under unsupported frequency, set the divider higher when there is reminder, use ceiling
139 operation, ceiling(a/b) = (a-1)/b + 1. */
140 val |= QuadSPI_MCR_SCLKCFG((srcClock_Hz - 1U) / config->baudRate);
141 base->MCR = val;
142 #endif /* FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL */
143
144 /* Set AHB buffer size and buffer master */
145 for (i = 0; i < (uint32_t)FSL_FEATURE_QSPI_AHB_BUFFER_COUNT; i++)
146 {
147 val = QuadSPI_BUF0CR_MSTRID(config->AHBbufferMaster[i]) | QuadSPI_BUF0CR_ADATSZ(config->AHBbufferSize[i] / 8U);
148 QSPI_AHB_BUFFER_REG(base, i) = val;
149 }
150 if (config->enableAHBbuffer3AllMaster)
151 {
152 base->BUF3CR |= QuadSPI_BUF3CR_ALLMST_MASK;
153 }
154 else
155 {
156 base->BUF3CR &= ~QuadSPI_BUF3CR_ALLMST_MASK;
157 }
158
159 /* Set watermark */
160 base->RBCT &= ~QuadSPI_RBCT_WMRK_MASK;
161 base->RBCT |= QuadSPI_RBCT_WMRK((uint32_t)config->rxWatermark - 1U);
162
163 #if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA)
164 base->TBCT &= ~QuadSPI_TBCT_WMRK_MASK;
165 base->TBCT |= QuadSPI_TBCT_WMRK((uint32_t)config->txWatermark - 1U);
166 #endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */
167
168 /* Enable QSPI module */
169 if (config->enableQspi)
170 {
171 QSPI_Enable(base, true);
172 }
173 }
174
175 /*!
176 * brief Gets default settings for QSPI.
177 *
178 * param config QSPI configuration structure.
179 */
QSPI_GetDefaultQspiConfig(qspi_config_t * config)180 void QSPI_GetDefaultQspiConfig(qspi_config_t *config)
181 {
182 /* Initializes the configure structure to zero. */
183 (void)memset(config, 0, sizeof(*config));
184
185 config->clockSource = 2U;
186 config->baudRate = 24000000U;
187 config->AHBbufferMaster[0] = 0xE;
188 config->AHBbufferMaster[1] = 0xE;
189 config->AHBbufferMaster[2] = 0xE;
190 config->enableAHBbuffer3AllMaster = true;
191 config->txWatermark = 8U;
192 config->rxWatermark = 8U;
193 config->enableQspi = true;
194 }
195
196 /*!
197 * brief Deinitializes the QSPI module.
198 *
199 * Clears the QSPI state and QSPI module registers.
200 * param base Pointer to QuadSPI Type.
201 */
QSPI_Deinit(QuadSPI_Type * base)202 void QSPI_Deinit(QuadSPI_Type *base)
203 {
204 QSPI_Enable(base, false);
205 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
206 CLOCK_DisableClock(s_qspiClock[QSPI_GetInstance(base)]);
207 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
208 }
209
210 /*!
211 * brief Configures the serial flash parameter.
212 *
213 * This function configures the serial flash relevant parameters, such as the size, command, and so on.
214 * The flash configuration value cannot have a default value. The user needs to configure it according to the
215 * QSPI features.
216 *
217 * param base Pointer to QuadSPI Type.
218 * param config Flash configuration parameters.
219 */
QSPI_SetFlashConfig(QuadSPI_Type * base,qspi_flash_config_t * config)220 void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config)
221 {
222 uint32_t address = FSL_FEATURE_QSPI_AMBA_BASE + config->flashA1Size;
223 uint32_t val = 0;
224 uint32_t i = 0;
225
226 /* Disable module */
227 QSPI_Enable(base, false);
228
229 /* Config the serial flash size */
230 base->SFA1AD = address;
231 address += config->flashA2Size;
232 base->SFA2AD = address;
233 #if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE)
234 address += config->flashB1Size;
235 base->SFB1AD = address;
236 address += config->flashB2Size;
237 base->SFB2AD = address;
238 #endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */
239
240 #if !defined(FSL_FEATURE_QSPI_HAS_NO_SFACR) || (!FSL_FEATURE_QSPI_HAS_NO_SFACR)
241 /* Set Word Addressable feature */
242 val = QuadSPI_SFACR_WA(config->enableWordAddress) | QuadSPI_SFACR_CAS(config->cloumnspace);
243 base->SFACR = val;
244 #endif /* FSL_FEATURE_QSPI_HAS_NO_SFACR */
245
246 /* Config look up table */
247 base->LUTKEY = 0x5AF05AF0U;
248 base->LCKCR = 0x2U;
249 for (i = 0; i < (uint32_t)FSL_FEATURE_QSPI_LUT_DEPTH; i++)
250 {
251 base->LUT[i] = config->lookuptable[i];
252 }
253 base->LUTKEY = 0x5AF05AF0U;
254 base->LCKCR = 0x1U;
255
256 #if !defined(FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH)
257 /* Config flash timing */
258 val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TDH(config->dataHoldTime) |
259 QuadSPI_FLSHCR_TCSH(config->CSSetupTime);
260 #else
261 val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TCSH(config->CSSetupTime);
262 #endif /* FSL_FEATURE_QSPI_HAS_NO_TDH */
263 base->FLSHCR = val;
264
265 /* Set flash endianness */
266 base->MCR &= ~QuadSPI_MCR_END_CFG_MASK;
267 base->MCR |= QuadSPI_MCR_END_CFG(config->endian);
268
269 /* Enable QSPI again */
270 QSPI_Enable(base, true);
271 }
272
273 #if (!defined(FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG)) || !FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG
274 /*!
275 * @brief Configures the serial flash DQS parameter.
276 *
277 * This function configures the serial flash DQS relevant parameters, such as the delay chain tap number, .
278 * DQS shift phase, whether need to inverse and the rxc sample clock selection.
279 *
280 * @param base Pointer to QuadSPI Type.
281 * @param config Dqs configuration parameters.
282 */
QSPI_SetDqsConfig(QuadSPI_Type * base,qspi_dqs_config_t * config)283 void QSPI_SetDqsConfig(QuadSPI_Type *base, qspi_dqs_config_t *config)
284 {
285 uint32_t soccrVal;
286 uint32_t mcrVal;
287
288 /* Disable module */
289 QSPI_Enable(base, false);
290
291 mcrVal = base->MCR;
292
293 mcrVal &= ~(QuadSPI_MCR_DQS_EN_MASK | QuadSPI_MCR_DQS_LAT_EN_MASK);
294 /* Enable DQS. */
295 mcrVal |= QuadSPI_MCR_DQS_EN_MASK;
296
297 /* Configure DQS phase, inverse and loopback atrribute */
298 soccrVal = base->SOCCR;
299 soccrVal &=
300 ~(QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK | QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK |
301 QuadSPI_SOCCR_DQS_PHASE_SEL_MASK | QuadSPI_SOCCR_DQS_INV_EN_MASK | QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK
302 #if defined(QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL_MASK)
303 | QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL_MASK
304 #endif
305 );
306 soccrVal |= QuadSPI_SOCCR_DQS_PHASE_SEL(config->shift);
307
308 switch (config->rxSampleClock)
309 {
310 case kQSPI_ReadSampleClkInternalLoopback:
311 soccrVal |= QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK;
312 break;
313 case kQSPI_ReadSampleClkExternalInputFromDqsPad:
314 mcrVal |= QuadSPI_MCR_DQS_LAT_EN_MASK;
315 break;
316 case kQSPI_ReadSampleClkLoopbackFromDqsPad:
317 soccrVal |= QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK;
318 break;
319 default:
320 assert(false);
321 break;
322 }
323
324 soccrVal |= (QuadSPI_SOCCR_DQS_INV_EN(config->enableDQSClkInverse) |
325 QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL(config->portADelayTapNum)
326 #if defined(QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL_MASK)
327 | QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL(config->portBDelayTapNum)
328 #endif
329 );
330
331 base->MCR = mcrVal;
332 base->SOCCR = soccrVal;
333
334 /* Enable QSPI again */
335 QSPI_Enable(base, true);
336 }
337 #endif /* FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG */
338
339 /*!
340 * brief Software reset for the QSPI logic.
341 *
342 * This function sets the software reset flags for both AHB and buffer domain and
343 * resets both AHB buffer and also IP FIFOs.
344 *
345 * param base Pointer to QuadSPI Type.
346 */
QSPI_SoftwareReset(QuadSPI_Type * base)347 void QSPI_SoftwareReset(QuadSPI_Type *base)
348 {
349 uint32_t i = 0;
350
351 /* Reset AHB domain and buffer domian */
352 base->MCR |= (QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);
353
354 /* Wait several time for the reset to finish, this method came from IC team */
355 for (i = 0; i < 100U; i++)
356 {
357 __NOP();
358 }
359
360 /* Disable QSPI module */
361 QSPI_Enable(base, false);
362
363 /* Clear the reset flags */
364 base->MCR &= ~(QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);
365
366 /* Enable QSPI module */
367 QSPI_Enable(base, true);
368 }
369
370 /*!
371 * brief Gets the Rx data register address used for DMA operation.
372 *
373 * This function returns the Rx data register address or Rx buffer address
374 * according to the Rx read area settings.
375 *
376 * param base Pointer to QuadSPI Type.
377 * return QSPI Rx data register address.
378 */
QSPI_GetRxDataRegisterAddress(QuadSPI_Type * base)379 uint32_t QSPI_GetRxDataRegisterAddress(QuadSPI_Type *base)
380 {
381 /* From RDBR */
382 if (0U != (base->RBCT & QuadSPI_RBCT_RXBRD_MASK))
383 {
384 return (uint32_t)(&(base->RBDR[0]));
385 }
386 else
387 {
388 /* From ARDB */
389 return FSL_FEATURE_QSPI_ARDB_BASE;
390 }
391 }
392
393 /*! brief Executes IP commands located in LUT table.
394 *
395 * param base Pointer to QuadSPI Type.
396 * param index IP command located in which LUT table index.
397 */
QSPI_ExecuteIPCommand(QuadSPI_Type * base,uint32_t index)398 void QSPI_ExecuteIPCommand(QuadSPI_Type *base, uint32_t index)
399 {
400 while (0U != (QSPI_GetStatusFlags(base) & ((uint32_t)kQSPI_Busy | (uint32_t)kQSPI_IPAccess)))
401 {
402 }
403 QSPI_ClearCommandSequence(base, kQSPI_IPSeq);
404
405 /* Write the seqid bit */
406 base->IPCR = ((base->IPCR & (~QuadSPI_IPCR_SEQID_MASK)) | QuadSPI_IPCR_SEQID(index / 4U));
407 }
408
409 /*! brief Executes AHB commands located in LUT table.
410 *
411 * param base Pointer to QuadSPI Type.
412 * param index AHB command located in which LUT table index.
413 */
QSPI_ExecuteAHBCommand(QuadSPI_Type * base,uint32_t index)414 void QSPI_ExecuteAHBCommand(QuadSPI_Type *base, uint32_t index)
415 {
416 while (0U != (QSPI_GetStatusFlags(base) & ((uint32_t)kQSPI_Busy | (uint32_t)kQSPI_AHBAccess)))
417 {
418 }
419 QSPI_ClearCommandSequence(base, kQSPI_BufferSeq);
420 base->BFGENCR = ((base->BFGENCR & (~QuadSPI_BFGENCR_SEQID_MASK)) | QuadSPI_BFGENCR_SEQID(index / 4U));
421 }
422
423 /*! brief Updates the LUT table.
424 *
425 * param base Pointer to QuadSPI Type.
426 * param index Which LUT index needs to be located. It should be an integer divided by 4.
427 * param cmd Command sequence array.
428 */
QSPI_UpdateLUT(QuadSPI_Type * base,uint32_t index,uint32_t * cmd)429 void QSPI_UpdateLUT(QuadSPI_Type *base, uint32_t index, uint32_t *cmd)
430 {
431 uint8_t i = 0;
432
433 /* Unlock the LUT */
434 base->LUTKEY = 0x5AF05AF0U;
435 base->LCKCR = 0x2U;
436
437 /* Write data into LUT */
438 for (i = 0; i < 4U; i++)
439 {
440 base->LUT[index + i] = *cmd;
441 cmd++;
442 }
443
444 /* Lcok LUT again */
445 base->LUTKEY = 0x5AF05AF0U;
446 base->LCKCR = 0x1U;
447 }
448
449 #if defined(FSL_FEATURE_QSPI_SOCCR_HAS_CLR_LPCAC) && (FSL_FEATURE_QSPI_SOCCR_HAS_CLR_LPCAC)
450
451 /*! brief Clears the QSPI cache.
452 *
453 * param base Pointer to QuadSPI Type.
454 */
QSPI_ClearCache(QuadSPI_Type * base)455 void QSPI_ClearCache(QuadSPI_Type *base)
456 {
457 uint32_t soccrVal;
458
459 soccrVal = base->SOCCR;
460 /* Write 1 to clear cache. */
461 base->SOCCR = (soccrVal | QuadSPI_SOCCR_CLR_LPCAC_MASK);
462
463 /* Write 0 to after cache is cleared. */
464 base->SOCCR = (soccrVal & (~QuadSPI_SOCCR_CLR_LPCAC_MASK));
465 }
466 #endif
467
468 /*! brief Set the RX buffer readout area.
469 *
470 * This function can set the RX buffer readout, from AHB bus or IP Bus.
471 * param base QSPI base address.
472 * param area QSPI Rx buffer readout area. AHB bus buffer or IP bus buffer.
473 */
QSPI_SetReadDataArea(QuadSPI_Type * base,qspi_read_area_t area)474 void QSPI_SetReadDataArea(QuadSPI_Type *base, qspi_read_area_t area)
475 {
476 base->RBCT &= ~QuadSPI_RBCT_RXBRD_MASK;
477 base->RBCT |= QuadSPI_RBCT_RXBRD(area);
478 }
479
480 /*!
481 * brief Receives data from data FIFO.
482 *
483 * param base QSPI base pointer
484 * return The data in the FIFO.
485 */
QSPI_ReadData(QuadSPI_Type * base)486 uint32_t QSPI_ReadData(QuadSPI_Type *base)
487 {
488 if (0U != (base->RBCT & QuadSPI_RBCT_RXBRD_MASK))
489 {
490 return base->RBDR[0];
491 }
492 else
493 {
494 /* Data from ARDB. */
495 return *((uint32_t *)FSL_FEATURE_QSPI_ARDB_BASE);
496 }
497 }
498
499 /*!
500 * brief Sends a buffer of data bytes using a blocking method.
501 * note This function blocks via polling until all bytes have been sent.
502 * param base QSPI base pointer
503 * param buffer The data bytes to send
504 * param size The number of data bytes to send
505 */
QSPI_WriteBlocking(QuadSPI_Type * base,uint32_t * buffer,size_t size)506 void QSPI_WriteBlocking(QuadSPI_Type *base, uint32_t *buffer, size_t size)
507 {
508 assert(size >= 16U);
509
510 uint32_t i = 0;
511
512 for (i = 0; i < size / 4U; i++)
513 {
514 /* Check if the buffer is full */
515 while (0U != (QSPI_GetStatusFlags(base) & (uint32_t)kQSPI_TxBufferFull))
516 {
517 }
518 base->TBDR = *buffer++;
519 }
520 }
521
522 /*!
523 * brief Receives a buffer of data bytes using a blocking method.
524 * note This function blocks via polling until all bytes have been sent. Users shall notice that
525 * this receive size shall not bigger than 64 bytes. As this interface is used to read flash status registers.
526 * For flash contents read, please use AHB bus read, this is much more efficiency.
527 *
528 * param base QSPI base pointer
529 * param buffer The data bytes to send
530 * param size The number of data bytes to receive
531 */
QSPI_ReadBlocking(QuadSPI_Type * base,uint32_t * buffer,size_t size)532 void QSPI_ReadBlocking(QuadSPI_Type *base, uint32_t *buffer, size_t size)
533 {
534 uint32_t i = 0;
535 uint32_t j = 0;
536 uint32_t temp = 0;
537 uint32_t level = (base->RBCT & QuadSPI_RBCT_WMRK_MASK) + 1U;
538
539 while (i < size / 4U)
540 {
541 /* Check if there is data */
542 if ((size / 4U - i) < level)
543 {
544 do
545 {
546 temp = (base->RBSR & QuadSPI_RBSR_RDBFL_MASK) >> QuadSPI_RBSR_RDBFL_SHIFT;
547 } while (0U == temp);
548 }
549 else
550 {
551 while ((QSPI_GetStatusFlags(base) & (uint32_t)kQSPI_RxWatermark) == 0U)
552 {
553 }
554 }
555
556 level = (level < (size / 4U - i)) ? level : (size / 4U - i);
557
558 /* Data from RBDR */
559 if (0U != (base->RBCT & QuadSPI_RBCT_RXBRD_MASK))
560 {
561 for (j = 0; j < level; j++)
562 {
563 buffer[i + j] = base->RBDR[j];
564 }
565 }
566 else
567 {
568 /* Data from ARDB. */
569 for (j = 0; j < level; j++)
570 {
571 buffer[i + j] = ((uint32_t *)FSL_FEATURE_QSPI_ARDB_BASE)[j];
572 }
573 }
574 i += level;
575
576 /* Clear the Buffer */
577 QSPI_ClearErrorFlag(base, (uint32_t)kQSPI_RxBufferDrain);
578 }
579 }
580