iLLD_TC27xD  1.0
IfxQspi_SpiMaster.c
Go to the documentation of this file.
1 /**
2  * \file IfxQspi_SpiMaster.c
3  * \brief QSPI SPIMASTER details
4  *
5  * \version iLLD_1_0_0_11_0
6  * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
7  *
8  *
9  * IMPORTANT NOTICE
10  *
11  *
12  * Infineon Technologies AG (Infineon) is supplying this file for use
13  * exclusively with Infineon's microcontroller products. This file can be freely
14  * distributed within development tools that are supporting such microcontroller
15  * products.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
21  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
22  *
23  */
24 
25 /******************************************************************************/
26 /*----------------------------------Includes----------------------------------*/
27 /******************************************************************************/
28 
29 #include "IfxQspi_SpiMaster.h"
30 
31 /** \addtogroup IfxLld_Qspi_SpiMaster_Channel
32  * \{ */
33 
34 /******************************************************************************/
35 /*-----------------------Private Function Prototypes--------------------------*/
36 /******************************************************************************/
37 
38 /** \brief Gets current active channel
39  * \param handle Module handle
40  * \return current active channel
41  */
42 static IfxQspi_SpiMaster_Channel *IfxQspi_SpiMaster_activeChannel(IfxQspi_SpiMaster *handle);
43 
44 /** \} */
45 
46 /** \addtogroup IfxLld_Qspi_SpiMaster_Support
47  * \{ */
48 
49 /******************************************************************************/
50 /*-----------------------Private Function Prototypes--------------------------*/
51 /******************************************************************************/
52 
53 /** \brief Active the SLSO pin.
54  * \param chHandle Module Channel handle
55  * \return None
56  */
57 static void IfxQspi_SpiMaster_activateSlso(IfxQspi_SpiMaster_Channel *chHandle);
58 
59 /** \brief Deactive the SLSO pin.
60  * \param chHandle Module Channel handle
61  * \return None
62  */
63 static void IfxQspi_SpiMaster_deactivateSlso(IfxQspi_SpiMaster_Channel *chHandle);
64 
65 /** \brief Locks the transfer and gets the current status of it.
66  * \param handle Module handle
67  * \return SpiIf_Status_ok if sending is done otherwise SpiIf_Status_busy.
68  */
69 static SpiIf_Status IfxQspi_SpiMaster_lock(IfxQspi_SpiMaster *handle);
70 
71 /** \brief Reads data from the Rx FIFO
72  * \param chHandle Module Channel handle
73  * \return None
74  */
75 static void IfxQspi_SpiMaster_read(IfxQspi_SpiMaster_Channel *chHandle);
76 
77 /** \brief Unlocks the transfers
78  * \param handle Module handle
79  * \return None
80  */
81 static void IfxQspi_SpiMaster_unlock(IfxQspi_SpiMaster *handle);
82 
83 /** \brief Writes data into the Tx FIFO
84  * \param chHandle Module Channel handle
85  * \return None
86  */
87 static void IfxQspi_SpiMaster_write(IfxQspi_SpiMaster_Channel *chHandle);
88 
89 /** \brief Writes Long/xxl data into the Tx FIFO
90  * \param chHandle Module Channel handle
91  * \return None
92  */
93 static void IfxQspi_SpiMaster_writeLong(IfxQspi_SpiMaster_Channel *chHandle);
94 
95 /** \} */
96 
97 /** \addtogroup IfxLld_Qspi_SpiMaster_DataStructures
98  * \{ */
99 
100 /******************************************************************************/
101 /*------------------------Private Variables/Constants-------------------------*/
102 /******************************************************************************/
103 
104 /** \brief dummy variable where recived data is placed
105  */
106 static uint32 IfxQspi_SpiMaster_dummyRxValue = 0;
107 
108 /** \brief dummy value to be transmitted
109  */
110 static const uint32 IfxQspi_SpiMaster_dummyTxValue = ~0;
111 
112 /** \} */
113 
114 /******************************************************************************/
115 /*-------------------------Function Implementations---------------------------*/
116 /******************************************************************************/
117 
118 static void IfxQspi_SpiMaster_activateSlso(IfxQspi_SpiMaster_Channel *chHandle)
119 {
121  IfxPort_setPinState(chHandle->slso.port, chHandle->slso.pinIndex, action);
122 }
123 
124 
125 static IfxQspi_SpiMaster_Channel *IfxQspi_SpiMaster_activeChannel(IfxQspi_SpiMaster *handle)
126 {
127  return (IfxQspi_SpiMaster_Channel *)handle->base.activeChannel;
128 }
129 
130 
131 static void IfxQspi_SpiMaster_deactivateSlso(IfxQspi_SpiMaster_Channel *chHandle)
132 {
134  IfxPort_setPinState(chHandle->slso.port, chHandle->slso.pinIndex, action);
135 }
136 
137 
138 SpiIf_Status IfxQspi_SpiMaster_exchange(IfxQspi_SpiMaster_Channel *chHandle, const void *src, void *dest, Ifx_SizeT count)
139 {
140  IfxQspi_SpiMaster *handle = (IfxQspi_SpiMaster *)chHandle->base.driver;
141  SpiIf_Status status = IfxQspi_SpiMaster_lock(handle);
142 
143  if (status == SpiIf_Status_ok)
144  {
145  /* initiate transfer when resource is free */
146  handle->base.activeChannel = &chHandle->base;
147  chHandle->base.flags.onTransfer = 1;
148  chHandle->base.tx.data = (void *)src;
149  chHandle->base.tx.remaining = count;
150  chHandle->firstWrite = TRUE;
151  chHandle->base.rx.data = dest;
152  chHandle->base.rx.remaining = count;
153 
154  if (chHandle->activateSlso != NULL_PTR)
155  {
156  chHandle->activateSlso(chHandle);
157  }
158 
159  if ((chHandle->mode == IfxQspi_SpiMaster_Mode_long) ||
161  {
162  IfxQspi_SpiMaster_writeLong((IfxQspi_SpiMaster_Channel *)chHandle);
163  }
164  else if (chHandle->mode == IfxQspi_SpiMaster_Mode_xxl)
165  {
166  handle->qspi->XXLCON.B.XDL = count - 1;
167  IfxQspi_SpiMaster_writeLong((IfxQspi_SpiMaster_Channel *)chHandle);
168  }
169  else
170  {
171  /* chHandle->mode == IfxQspi_SpiMaster_Mode_ShortCont*/
172  chHandle->base.txHandler(handle->base.activeChannel);
173  }
174  }
175 
176  return status;
177 }
178 
179 
181 {
182  {
183  SpiIf_ChConfig chConfig;
184  IfxQspi_SpiMaster *handle = (IfxQspi_SpiMaster *)chHandle->base.driver->driver;
185  Ifx_QSPI *qspiSFR = handle->qspi;
186  Ifx_QSPI_ECON econ;
187  econ.U = qspiSFR->ECON[chHandle->channelId % 8].U;
188 
189  chConfig.baudrate = IfxQspi_calcRealBaudrate(qspiSFR, chHandle->channelId % 8);
190  chConfig.driver = chHandle->base.driver;
191  chConfig.errorChecks.baudrate = 0;
192  chConfig.errorChecks.phase = 0;
193  chConfig.errorChecks.receive = 0;
194  chConfig.errorChecks.reserved = 0;
195  chConfig.errorChecks.transmit = 0;
196  chConfig.mode.autoCS = (chHandle->activateSlso == (&IfxQspi_SpiMaster_activateSlso)) && (chHandle->deactivateSlso == (&IfxQspi_SpiMaster_deactivateSlso));
198  chConfig.mode.csActiveLevel = chHandle->slsoActiveState;
199  chConfig.mode.csInactiveDelay = chHandle->bacon.B.IDLE;
200  chConfig.mode.csLeadDelay = chHandle->bacon.B.LEAD;
201  chConfig.mode.csTrailDelay = chHandle->bacon.B.TRAIL;
202  chConfig.mode.dataHeading = chHandle->bacon.B.MSB == 0 ? SpiIf_DataHeading_lsbFirst : SpiIf_DataHeading_msbFirst;
203  chConfig.mode.dataWidth = chHandle->bacon.B.DL + 1;
204  chConfig.mode.enabled = 0;
205  chConfig.mode.loopback = qspiSFR->GLOBALCON.B.LB;
206  chConfig.mode.parityCheck = econ.B.PAREN;
207  chConfig.mode.parityMode = chHandle->bacon.B.PARTYP == 0 ? Ifx_ParityMode_even : Ifx_ParityMode_odd;
209 
210  return chConfig;
211  }
212 }
213 
214 
216 {
217  SpiIf_Status status = SpiIf_Status_ok;
218 
219  if ((chHandle->base.flags.onTransfer != 0) || (chHandle->base.driver->sending != 0))
220  {
221  status = SpiIf_Status_busy;
222  }
223 
224  return status;
225 }
226 
227 
229 {
230  IfxQspi_SpiMaster *handle = chConfig->base.driver->driver;
231  Ifx_QSPI *qspiSFR = handle->qspi;
232 
233  chHandle->base.driver = chConfig->base.driver;
234  chHandle->channelId = (IfxQspi_ChannelId)chConfig->sls.output.pin->slsoNr;
235  chHandle->base.flags.onTransfer = FALSE;
236  chHandle->channelBasedCs = chConfig->channelBasedCs;
237  chHandle->mode = chConfig->mode;
238 
239  //Loop back configuration.
240  qspiSFR->GLOBALCON.B.LB = chConfig->base.mode.loopback;
241  uint8 cs = chHandle->channelId % 8;
242 
243  {
244  qspiSFR->ECON[cs].U = IfxQspi_calculateExtendedConfigurationValue(qspiSFR, cs, &chConfig->base);
245  chHandle->bacon.U = IfxQspi_calculateBasicConfigurationValue(qspiSFR, chHandle->channelId, &chConfig->base.mode, chConfig->base.baudrate);
246 
247  { /* QSPI chip-select line */
248  uint32 mask = 1U << chHandle->channelId;
249  uint32 oen = mask << 16;
250  uint32 aol = (((chConfig->base.mode.csActiveLevel == Ifx_ActiveState_low) ? 0 : 1) << chHandle->channelId);
251  __ldmst(&qspiSFR->SSOC.U, (mask | (mask << 16)), (aol | oen));
252  }
253  }
254  chHandle->base.baudrate = IfxQspi_calcRealBaudrate(qspiSFR, (chHandle->bacon.B.CS & 0x7U));
255 
256  /* chip-select output pin */
257  const IfxQspi_Slso_Out *slso = chConfig->sls.output.pin;
258  chHandle->slso = slso->pin;
259  chHandle->slsoActiveState = chConfig->base.mode.csActiveLevel;
260 
261  if (chHandle->slso.port == NULL_PTR)
262  {
263  chHandle->activateSlso = NULL_PTR;
264  chHandle->deactivateSlso = NULL_PTR;
265  }
266  else
267  {
268  if (!chConfig->base.mode.autoCS)
269  {
270  chHandle->activateSlso = &IfxQspi_SpiMaster_activateSlso;
271  chHandle->deactivateSlso = &IfxQspi_SpiMaster_deactivateSlso;
272 
273  /** - Override the SLSO manually as general-purpose output */
274  chHandle->deactivateSlso(chHandle);
275  IfxQspi_initSlso(slso, chConfig->sls.output.mode, chConfig->sls.output.driver, IfxPort_OutputIdx_general);
276  }
277  else
278  {
279  chHandle->activateSlso = NULL_PTR;
280  chHandle->deactivateSlso = NULL_PTR;
281  IfxQspi_initSlso(slso, chConfig->sls.output.mode, chConfig->sls.output.driver, slso->select);
282  }
283  }
284 
285  chHandle->dataWidth = chConfig->base.mode.dataWidth;
286  chHandle->base.txHandler = (TxRxHandler) & IfxQspi_SpiMaster_write;
287  chHandle->base.rxHandler = (TxRxHandler) & IfxQspi_SpiMaster_read;
288 
289  if (handle->dma.useDma)
290  {
291  Ifx_DMA *dmaSFR = &MODULE_DMA;
292  IfxDma_setChannelDestinationAddress(dmaSFR, handle->dma.txDmaChannelId, (uint32 *)&qspiSFR->DATAENTRY[cs].U);
293  }
294 
295  return SpiIf_Status_ok;
296 }
297 
298 
300 {
301  SpiIf_initChannelConfig(&chConfig->base, &handle->base);
302  chConfig->sls.output.pin = NULL_PTR;
305  chConfig->sls.input.pin = NULL_PTR;
309 }
310 
311 
313 {
314  Ifx_QSPI *qspiSFR = config->qspi;
315 
316  Ifx_DMA *dmaSFR = &MODULE_DMA;
317 
318  /* handle.base must be at offset 0 to be compatible with the standard interface SscIf */
319  {
321  IfxScuWdt_clearCpuEndinit(password);
324  IfxScuWdt_setCpuEndinit(password);
325  }
326 
327  { /* Configure GLOBAL, Note: at the moment default values for GLOBAL */
328  Ifx_QSPI_GLOBALCON globalcon;
329  globalcon.U = 0;
330  globalcon.B.TQ = IfxQspi_calculateTimeQuantumLength(qspiSFR, config->base.maximumBaudrate);
331  globalcon.B.EXPECT = IfxQspi_ExpectTimeout_2097152; /* 2^(EXPECT+6) : timeout for expect phase in Tqspi */
332  //globalcon.B.LB = 0 ; /* 0 : disable loop-back w*/
333  //globalcon.B.DEL0 = 0; /* 0 : disable delayed mode for SLSO 0 */
334  //globalcon.B.STROBE = 0; /* (STROBE+1) : strobe delay for SLSO 0 in Tq */
335  //globalcon.B.SRF = 0; /* 0 : disable stop-on-RXFIFO full feature */
336  //globalcon.B.STIP = 0; /* 0 : MRST = 0 when QSPI is deselected in slave mode */
337  //globalcon.B.EN = 0; /* 0 : PAUSE requested, 1 : RUN requested */
338  globalcon.B.MS = IfxQspi_Mode_master; /* select master mode */
339  globalcon.B.AREN = (config->pauseOnBaudrateSpikeErrors != FALSE) ? 1U : 0U;
340  globalcon.B.RESETS = 1;
341  qspiSFR->GLOBALCON.U = globalcon.U;
342  }
343 
344  { /* Configure interrupt requests */
345  Ifx_QSPI_GLOBALCON1 globalcon1;
346  globalcon1.U = 0;
347  //TODO: globalcon1.B.ERRORENS;
348  globalcon1.B.TXEN = (config->base.txPriority > 0) || (config->dma.useDma);
349  globalcon1.B.RXEN = (config->base.rxPriority > 0) || (config->dma.useDma);
350  globalcon1.B.TXFIFOINT = config->txFifoThreshold;
351  globalcon1.B.RXFIFOINT = config->rxFifoThreshold;
352  qspiSFR->GLOBALCON1.U = globalcon1.U;
353  }
354 
355  /* Configure I/O pins for master mode */
356  const IfxQspi_SpiMaster_Pins *pins = config->pins;
357 
358  if (pins != NULL_PTR)
359  {
360  const IfxQspi_Sclk_Out *sclkOut = pins->sclk;
361 
362  if (sclkOut != NULL_PTR)
363  {
364  IfxQspi_initSclkOutPin(sclkOut, pins->sclkMode, pins->pinDriver);
365  }
366 
367  const IfxQspi_Mtsr_Out *mtsrOut = pins->mtsr;
368 
369  if (mtsrOut != NULL_PTR)
370  {
371  IfxQspi_initMtsrOutPin(mtsrOut, pins->mtsrMode, pins->pinDriver);
372  }
373 
374  const IfxQspi_Mrst_In *mrstIn = pins->mrst;
375 
376  if (mrstIn != NULL_PTR)
377  {
378  IfxQspi_initMrstInPin(mrstIn, pins->mrstMode);
379  }
380  }
381 
382  handle->qspi = qspiSFR;
383  handle->base.driver = handle;
384  handle->base.sending = 0U;
385  handle->base.activeChannel = NULL_PTR;
386 
389 
390  if (config->dma.useDma)
391  {
394  }
395  else
396  {
399  }
400 
402 
403  if (config->dma.useDma)
404  {
405  handle->dma.useDma = TRUE;
406  IfxDma_Dma dma;
407  IfxDma_Dma_createModuleHandle(&dma, dmaSFR);
408 
410  IfxDma_Dma_initChannelConfig(&dmaCfg, &dma);
411 
412  {
413  handle->dma.txDmaChannelId = config->dma.txDmaChannelId;
414  dmaCfg.channelId = handle->dma.txDmaChannelId;
415  dmaCfg.hardwareRequestEnabled = FALSE; // will be triggered from FFT service request
416  dmaCfg.channelInterruptEnabled = TRUE; // trigger interrupt after transaction
417 
418  // source address and transfer count will be configured during runtime
419  dmaCfg.sourceAddress = 0;
422  dmaCfg.transferCount = 0;
424 
425  // destination address is fixed; use circular mode to stay at this address for each move
426  dmaCfg.destinationAddress = (uint32)&qspiSFR->DATAENTRY[0].U;
429 
433 
434  IfxDma_Dma_initChannel(&handle->dma.txDmaChannel, &dmaCfg);
435  }
436 
437  {
438  handle->dma.rxDmaChannelId = config->dma.rxDmaChannelId;
439  dmaCfg.channelId = handle->dma.rxDmaChannelId;
440  dmaCfg.hardwareRequestEnabled = FALSE; // will be triggered from qspi service request
441  dmaCfg.channelInterruptEnabled = TRUE; // trigger interrupt after transaction
442 
443  // source address is fixed; use circular mode to stay at this address for each move
444  dmaCfg.sourceAddress = (uint32)&qspiSFR->RXEXIT.U;
447 
448  // destination address and transfer count will be configured during runtime
449  dmaCfg.destinationAddress = 0;
452  dmaCfg.transferCount = 0;
453 
458 
459  IfxDma_Dma_initChannel(&handle->dma.rxDmaChannel, &dmaCfg);
460  }
461  /* Dma channel interrupt configuration */
462  {
463  volatile Ifx_SRC_SRCR *src = IfxDma_getSrcPointer(dmaSFR, (IfxDma_ChannelId)config->dma.txDmaChannelId);
464  IfxSrc_init(src, config->base.isrProvider, config->base.txPriority);
465  IfxSrc_enable(src);
466 
468  IfxSrc_init(src, config->base.isrProvider, config->base.rxPriority);
469  IfxSrc_enable(src);
470  }
471  }
472 
473  /* Qspi interrupt configuration */
474  {
476 
477  if (handle->dma.useDma)
478  {
479  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
481  IfxSrc_enable(src);
482 
483  src = IfxQspi_getReceiveSrc(qspiSFR);
485  IfxSrc_enable(src);
486  }
487  else
488  {
489  if (config->base.txPriority != 0)
490  {
491  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
492  IfxSrc_init(src, config->base.isrProvider, config->base.txPriority);
493  IfxSrc_enable(src);
494  }
495 
496  if (config->base.rxPriority != 0)
497  {
498  volatile Ifx_SRC_SRCR *src = IfxQspi_getReceiveSrc(qspiSFR);
499  IfxSrc_init(src, config->base.isrProvider, config->base.rxPriority);
500  IfxSrc_enable(src);
501  }
502  }
503  }
504 
505  IfxQspi_run(qspiSFR);
506 }
507 
508 
510 {
511  SpiIf_initConfig(&config->base);
512  config->qspi = qspi;
513  config->allowSleepMode = FALSE;
518  config->pins = NULL_PTR;
521  config->dma.useDma = FALSE;
522 }
523 
524 
526 {
527  Ifx_DMA *dmaSFR = &MODULE_DMA;
528  IfxDma_ChannelId rxDmaChannelId = qspiHandle->dma.rxDmaChannelId;
529  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(qspiHandle);
530 
531  if (IfxDma_getAndClearChannelInterrupt(dmaSFR, rxDmaChannelId))
532  {
533  if (chHandle->deactivateSlso != NULL_PTR)
534  {
535  chHandle->deactivateSlso(chHandle);
536  }
537 
538  chHandle->base.flags.onTransfer = 0;
539  IfxQspi_SpiMaster_unlock((IfxQspi_SpiMaster *)chHandle->base.driver);
540  }
541 
543 }
544 
545 
547 {
548  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(qspiHandle);
549  Ifx_DMA *dmaSFR = &MODULE_DMA;
550  IfxDma_ChannelId txDmaChannelId = qspiHandle->dma.txDmaChannelId;
551  Ifx_QSPI *qspiSFR = qspiHandle->qspi;
552  SpiIf_Job *job = &chHandle->base.tx;
553 
554  if (IfxDma_getAndClearChannelPatternDetectionInterrupt(dmaSFR, txDmaChannelId))
555  {
556  // DMA_TC.031 workaround ..
557  IfxDma_getAndClearChannelInterrupt(dmaSFR, txDmaChannelId);
558  }
559  else if ((chHandle->mode == IfxQspi_SpiMaster_Mode_long) ||
561  {
562  IfxDma_getAndClearChannelInterrupt(dmaSFR, txDmaChannelId);
563  IfxDma_disableChannelTransaction(dmaSFR, txDmaChannelId);
564  }
565  else if (chHandle->mode == IfxQspi_SpiMaster_Mode_xxl)
566  {
567  IfxDma_getAndClearChannelInterrupt(dmaSFR, txDmaChannelId);
568  IfxDma_disableChannelTransaction(dmaSFR, txDmaChannelId);
569  }
570  else if (IfxDma_getAndClearChannelInterrupt(dmaSFR, txDmaChannelId) && (job->remaining > 1))
571  {
572  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
573  IfxDma_disableChannelTransaction(dmaSFR, txDmaChannelId);
574 
575  if (job->data == NULL_PTR)
576  {
577  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
578  IfxQspi_writeTransmitFifo(qspiSFR, ~0);
579  }
580  else
581  {
582  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
583 
584  if (chHandle->dataWidth <= 8)
585  {
586  IfxQspi_writeTransmitFifo(qspiSFR, ((uint8 *)job->data)[job->remaining - 1]);
587  }
588  else if (chHandle->dataWidth <= 16)
589  {
590  IfxQspi_writeTransmitFifo(qspiSFR, ((uint16 *)job->data)[job->remaining - 1]);
591  }
592  else
593  {
594  IfxQspi_writeTransmitFifo(qspiSFR, ((uint32 *)job->data)[job->remaining - 1]);
595  }
596  }
597  }
598 }
599 
600 
602 {
603  Ifx_QSPI *qspiSFR = handle->qspi;
604  uint16 errorFlags = IfxQspi_getErrorFlags(qspiSFR);
606  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(handle);
607  Ifx_DMA *dmaSFR = &MODULE_DMA;
608 
609  /* store all the flags in the variable */
610 
611  if ((errorFlags & IfxQspi_Error_parity) == 1)
612  {
613  chHandle->errorFlags.parityError = 1;
614  }
615 
616  if ((errorFlags & IfxQspi_Error_configuration) == 1)
617  {
618  chHandle->errorFlags.configurationError = 1;
619  }
620 
621  if ((errorFlags & IfxQspi_Error_baudrate) == 1)
622  {
623  chHandle->errorFlags.baudrateError = 1;
624  }
625 
626  if ((errorFlags & IfxQspi_Error_expectTimeout) == 1)
627  {
628  chHandle->errorFlags.expectTimeoutError = 1;
629  }
630 
631  if ((errorFlags & IfxQspi_Error_txfifoOverflow) == 1)
632  {
633  chHandle->errorFlags.txFifoOverflowError = 1;
634  }
635 
636  if ((errorFlags & IfxQspi_Error_txfifoUnderflow) == 1)
637  {
638  chHandle->errorFlags.txFifoUnderflowError = 1;
639  }
640 
641  if ((errorFlags & IfxQspi_Error_rxfifoOverflow) == 1)
642  {
643  chHandle->errorFlags.rxFifoOverflowError = 1;
644  }
645 
646  if ((errorFlags & IfxQspi_Error_rxfifoUnderflow) == 1)
647  {
648  chHandle->errorFlags.rxFifoUnderflowError = 1;
649  }
650 
651  if (errorFlags)
652  {
653  if (chHandle->deactivateSlso != NULL_PTR)
654  {
655  chHandle->deactivateSlso(chHandle);
656  }
657 
658  chHandle->base.flags.onTransfer = 0;
659  IfxQspi_SpiMaster_unlock((IfxQspi_SpiMaster *)chHandle->base.driver);
660  }
661 
662  if (handle->dma.useDma)
663  {
666  }
667 }
668 
669 
671 {
672  Ifx_QSPI *qspiSFR = handle->qspi;
673  IfxQspi_PhaseTransitionEvent ptEvent = 0;
674 
675  if (qspiSFR->STATUS.B.PT1F)
676  {
677  qspiSFR->FLAGSCLEAR.B.PT1C = 1;
678  ptEvent = qspiSFR->GLOBALCON1.B.PT1; //
679  }
680  else if (qspiSFR->STATUS.B.PT2F)
681  {
682  qspiSFR->FLAGSCLEAR.B.PT2C = 1;
683  ptEvent = qspiSFR->GLOBALCON1.B.PT2; //
684  }
685 
686  return ptEvent;
687 }
688 
689 
691 {
692  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(handle);
693  chHandle->base.rxHandler(&chHandle->base);
694  handle->base.rxCount++;
695 }
696 
697 
699 {
700  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(handle);
701  chHandle->base.txHandler(&chHandle->base);
702  handle->base.txCount++;
703 }
704 
705 
707 {
708  Ifx_QSPI *qspiSFR = handle->qspi;
709  IfxQspi_PhaseTransitionEvent ptEvent = 0;
710 
711  if (qspiSFR->STATUS.B.USRF)
712  {
713  qspiSFR->FLAGSCLEAR.B.USRC = 1;
714  ptEvent = qspiSFR->GLOBALCON1.B.PT1; //
715  }
716 
717  return ptEvent;
718 }
719 
720 
721 static SpiIf_Status IfxQspi_SpiMaster_lock(IfxQspi_SpiMaster *handle)
722 {
723  sint32 sending = __swap((void *)&handle->base.sending, 1UL);
724  return (sending == 0) ? SpiIf_Status_ok : SpiIf_Status_busy;
725 }
726 
727 
728 void IfxQspi_SpiMaster_packLongModeBuffer(IfxQspi_SpiMaster_Channel *chHandle, void *data, uint32 *longFifoBuffer, Ifx_SizeT dataLength)
729 {
730  int i;
731  boolean isFirst = 0;
732  uint8 *src = (uint8 *)data;
733  uint32 baconDL;
734 
735  baconDL = 16;
736 
738  {
739  chHandle->bacon.B.BYTE = 1;
740  chHandle->bacon.B.LAST = 0;
741  }
742  else if (chHandle->mode == IfxQspi_SpiMaster_Mode_long)
743  {
744  chHandle->bacon.B.BYTE = 1;
745  chHandle->bacon.B.LAST = 1;
746  }
747  else
748  {
750  }
751 
752  while (dataLength > 0)
753  {
754  if (dataLength <= 16)
755  {
756  baconDL = dataLength;
757  chHandle->bacon.B.LAST = 1;
758  }
759 
760  dataLength -= (Ifx_SizeT)baconDL;
761 
762  /* FILL BACON */
763  if (isFirst == 0)
764  {
765  isFirst = 1;
766  }
767  else
768  {
769  chHandle->bacon.B.DL = baconDL - 1;
770  *longFifoBuffer = chHandle->bacon.U;
771  longFifoBuffer++;
772  }
773 
774  for (i = 0; i < baconDL / 4; i++)
775  {
776  *longFifoBuffer = *((uint32 *)src);
777  longFifoBuffer++;
778  src += 4;
779  }
780 
781  /* Copy Last bytes */
782  switch (baconDL % 4)
783  {
784  case 1:
785  *longFifoBuffer = *src;
786  break;
787  case 2:
788  *longFifoBuffer = *src | (*(src + 1) << 8);
789  break;
790  case 3:
791  *longFifoBuffer = *src | (*(src + 1) << 8) | (*(src + 2) << 16);
792  break;
793  }
794  }
795 }
796 
797 
798 static void IfxQspi_SpiMaster_read(IfxQspi_SpiMaster_Channel *chHandle)
799 {
800  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
801  Ifx_QSPI *qspiSFR = handle->qspi;
802  SpiIf_Job *job = &chHandle->base.rx;
803 
805  count = __min(job->remaining, count);
806 
807  if (job->data == NULL_PTR)
808  {
809  // no data should be buffered: do dummy reads
810  int i;
811 
812  for (i = 0; i < count; ++i)
813  {
814  IfxQspi_readReceiveFifo(qspiSFR);
815  }
816  }
817  else
818  {
819  if (chHandle->dataWidth <= 8)
820  {
821  IfxQspi_read8(qspiSFR, job->data, count);
822  job->data = &(((uint8 *)job->data)[count]);
823  }
824  else if (chHandle->dataWidth <= 16)
825  {
826  IfxQspi_read16(qspiSFR, job->data, count);
827  job->data = &(((uint16 *)job->data)[count]);
828  }
829  else
830  {
831  IfxQspi_read32(qspiSFR, job->data, count);
832  job->data = &(((uint32 *)job->data)[count]);
833  }
834  }
835 
836  job->remaining = job->remaining - count;
837 
838  if (job->remaining == 0)
839  {
840  if (chHandle->deactivateSlso != NULL_PTR)
841  {
842  chHandle->deactivateSlso(chHandle);
843  }
844 
845  chHandle->base.flags.onTransfer = 0;
846  IfxQspi_SpiMaster_unlock((IfxQspi_SpiMaster *)chHandle->base.driver);
847  }
848 }
849 
850 
852 {
853  {
854  IfxQspi_SpiMaster *handle = (IfxQspi_SpiMaster *)chHandle->base.driver->driver;
855  Ifx_QSPI *qspiSFR = handle->qspi;
856  SpiIf_ChConfig chConfig;
857  chConfig = IfxQspi_SpiMaster_getChannelConfig(chHandle);
858  chConfig.baudrate = baudrate;
859  uint8 cs = chHandle->channelId % 8;
860  qspiSFR->ECON[cs].U = IfxQspi_calculateExtendedConfigurationValue(qspiSFR, cs, &chConfig);
861  chHandle->bacon.U = IfxQspi_calculateBasicConfigurationValue(qspiSFR, chHandle->channelId, &chConfig.mode, chConfig.baudrate);
862  chHandle->base.baudrate = IfxQspi_calcRealBaudrate(qspiSFR, cs);
863  return SpiIf_Status_ok;
864  }
865 }
866 
867 
868 static void IfxQspi_SpiMaster_unlock(IfxQspi_SpiMaster *handle)
869 {
870  handle->base.sending = 0UL;
871 }
872 
873 
874 static void IfxQspi_SpiMaster_write(IfxQspi_SpiMaster_Channel *chHandle)
875 {
876  SpiIf_Job *job = &chHandle->base.tx;
877  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
878 
879  if (handle->dma.useDma)
880  {
881  Ifx_DMA *dmaSFR = &MODULE_DMA;
882 
883  Ifx_QSPI *qspiSFR = handle->qspi;
884  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
885 
886  IfxDma_ChannelId txDmaChannelId = handle->dma.txDmaChannelId;
887  IfxDma_ChannelId rxDmaChannelId = handle->dma.rxDmaChannelId;
888 
889  boolean interruptState = IfxCpu_disableInterrupts();
890 
891  if (job->remaining > 1)
892  {
893  IfxDma_setChannelTransferCount(dmaSFR, txDmaChannelId, job->remaining - 1);
894 
895  if (chHandle->dataWidth <= 8)
896  {
898  }
899  else if (chHandle->dataWidth <= 16)
900  {
902  }
903  else
904  {
906  }
907 
908  if (job->data == NULL_PTR)
909  {
910  IfxDma_setChannelSourceAddress(dmaSFR, txDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), &IfxQspi_SpiMaster_dummyTxValue));
913  /* need to enable circular buffering to avoid increment higher than 4 bytes */
914  /* we must do this direct why we don't have function for this */
915  dmaSFR->CH[txDmaChannelId].ADICR.B.SCBE = TRUE;
916  }
917  else
918  {
919  IfxDma_setChannelSourceAddress(dmaSFR, txDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), job->data));
922  /* maybe circular buffering was enabled by other call, we disable the circular buffering */
923  /* we must do this direct why we don't have function for this */
924  dmaSFR->CH[txDmaChannelId].ADICR.B.SCBE = FALSE;
925  }
926 
927  IfxDma_setChannelDestinationAddress(dmaSFR, txDmaChannelId, (void *)&qspiSFR->DATAENTRY[0].U);
930 
931  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
932  }
933 
934  /* Receive config */
935  IfxDma_setChannelTransferCount(dmaSFR, rxDmaChannelId, job->remaining);
936 
937  if (chHandle->dataWidth <= 8)
938  {
940  }
941  else if (chHandle->dataWidth <= 16)
942  {
944  }
945  else
946  {
948  }
949 
950  if (chHandle->base.rx.data == NULL_PTR)
951  {
952  IfxDma_setChannelDestinationAddress(dmaSFR, rxDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), &IfxQspi_SpiMaster_dummyRxValue));
955  /* need to enable circular buffering to avoid increment higher than 4 bytes */
956  /* we must do this direct why we don't have function for this */
957  dmaSFR->CH[rxDmaChannelId].ADICR.B.DCBE = TRUE;
958  }
959  else
960  {
961  IfxDma_setChannelDestinationAddress(dmaSFR, rxDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), chHandle->base.rx.data));
964  /* maybe circular buffering was enabled by other call, we disable the circular buffering */
965  /* we must do this direct why we don't have function for this */
966  dmaSFR->CH[rxDmaChannelId].ADICR.B.DCBE = FALSE;
967  }
968 
969  IfxDma_clearChannelInterrupt(dmaSFR, rxDmaChannelId);
970  IfxQspi_flushTransmitFifo(qspiSFR);
971  IfxQspi_flushReceiveFifo(qspiSFR);
973  src = IfxQspi_getTransmitSrc(qspiSFR);
974  IfxSrc_clearRequest(src);
975  src = IfxQspi_getReceiveSrc(qspiSFR);
976  IfxSrc_clearRequest(src);
977  src = IfxQspi_getErrorSrc(qspiSFR);
978  IfxSrc_clearRequest(src);
979  IfxDma_clearChannelInterrupt(dmaSFR, rxDmaChannelId);
980  IfxDma_enableChannelTransaction(dmaSFR, rxDmaChannelId);
981 
982  if (job->remaining > 1)
983  {
984  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
985  IfxDma_enableChannelTransaction(dmaSFR, txDmaChannelId);
986 
988  {
990  }
991  else
992  {
993  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
994  }
995  }
996  else
997  {
998  if (job->data == NULL_PTR)
999  {
1000  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1001  IfxQspi_writeTransmitFifo(qspiSFR, ~0);
1002  }
1003  else
1004  {
1005  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1006 
1007  if (chHandle->dataWidth <= 8)
1008  {
1009  IfxQspi_writeTransmitFifo(qspiSFR, ((uint8 *)job->data)[job->remaining - 1]);
1010  }
1011  else if (chHandle->dataWidth <= 16)
1012  {
1013  IfxQspi_writeTransmitFifo(qspiSFR, ((uint16 *)job->data)[job->remaining - 1]);
1014  }
1015  else
1016  {
1017  IfxQspi_writeTransmitFifo(qspiSFR, ((uint32 *)job->data)[job->remaining - 1]);
1018  }
1019  }
1020  }
1021 
1022  IfxCpu_restoreInterrupts(interruptState);
1023  }
1024  else
1025  {
1026  if (job->remaining > 0)
1027  {
1028  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
1029  Ifx_QSPI *qspiSFR = handle->qspi;
1030  uint8 cs = chHandle->bacon.B.CS;
1031 
1032  // following operation must be atomic (FIXME actually, we would only have to stall the Tx interrupt)
1033  boolean interruptState = IfxCpu_disableInterrupts();
1034  Ifx_SizeT count = (Ifx_SizeT)(IFXQSPI_HWFIFO_DEPTH - 1 - IfxQspi_getTransmitFifoLevel(qspiSFR)); // -1, since BACON allocates one FIFO entry
1035  count = __min(job->remaining, count);
1036 
1037  if (count > 0)
1038  {
1039  job->remaining = job->remaining - count;
1040 
1041  // push BACON into FIFO before first data word
1042  if (chHandle->firstWrite == TRUE)
1043  {
1044  chHandle->firstWrite = FALSE;
1045 
1047  {
1048  IfxQspi_writeBasicConfigurationBeginStream(qspiSFR, chHandle->bacon.U);
1049  }
1050  else
1051  {
1052  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1053  }
1054  }
1055 
1056  // we have to push another BACON into FIFO before the last data word
1057  boolean lastWrite = job->remaining == 0;
1058 
1059  if (job->data == NULL_PTR)
1060  {
1061  // no data should be sent (only received): send all-1
1062  int i;
1063 
1064  if (lastWrite)
1065  {
1066  for (i = 0; i < count - 1; ++i)
1067  {
1068  IfxQspi_writeTransmitFifo(qspiSFR, ~0);
1069  }
1070 
1071  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1072  IfxQspi_writeTransmitFifo(qspiSFR, ~0);
1073  }
1074  else
1075  {
1076  for (i = 0; i < count; ++i)
1077  {
1078  IfxQspi_writeTransmitFifo(qspiSFR, ~0);
1079  }
1080  }
1081  }
1082  else
1083  {
1084  if (chHandle->dataWidth <= 8)
1085  {
1086  if (lastWrite)
1087  {
1088  if (count >= 2)
1089  {
1090  IfxQspi_write8(qspiSFR, cs, job->data, count - 1);
1091  }
1092 
1093  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1094  IfxQspi_writeTransmitFifo(qspiSFR, ((uint8 *)job->data)[count - 1]);
1095  }
1096  else
1097  {
1098  IfxQspi_write8(qspiSFR, cs, job->data, count);
1099  }
1100 
1101  job->data = &(((uint8 *)job->data)[count]);
1102  }
1103  else if (chHandle->dataWidth <= 16)
1104  {
1105  if (lastWrite)
1106  {
1107  if (count >= 2)
1108  {
1109  IfxQspi_write16(qspiSFR, cs, job->data, count - 1);
1110  }
1111 
1112  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1113  IfxQspi_writeTransmitFifo(qspiSFR, ((uint16 *)job->data)[count - 1]);
1114  }
1115  else
1116  {
1117  IfxQspi_write16(qspiSFR, cs, job->data, count);
1118  job->data = &(((uint16 *)job->data)[count]);
1119  }
1120  }
1121  else
1122  {
1123  if (lastWrite)
1124  {
1125  if (count >= 2)
1126  {
1127  IfxQspi_write32(qspiSFR, cs, job->data, count - 1);
1128  }
1129 
1130  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
1131  IfxQspi_writeTransmitFifo(qspiSFR, ((uint32 *)job->data)[count - 1]);
1132  }
1133  else
1134  {
1135  IfxQspi_write32(qspiSFR, cs, job->data, count);
1136  job->data = &(((uint32 *)job->data)[count]);
1137  }
1138  }
1139  }
1140  }
1141 
1142  IfxCpu_restoreInterrupts(interruptState);
1143  }
1144  }
1145 }
1146 
1147 
1148 static void IfxQspi_SpiMaster_writeLong(IfxQspi_SpiMaster_Channel *chHandle)
1149 {
1150  SpiIf_Job *job = &chHandle->base.tx;
1151  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
1152  uint8 fifosize = IFXQSPI_FIFO32BITSIZE(job->remaining);
1153 
1154  if (chHandle->mode != IfxQspi_SpiMaster_Mode_xxl)
1155  {
1156  fifosize = fifosize + IFXQSPI_BACONSIZE(job->remaining) - 1; // combining this line and above doesn't work
1157  }
1158 
1159  if (handle->dma.useDma)
1160  {
1161  Ifx_DMA *dmaSFR = &MODULE_DMA;
1162 
1163  Ifx_QSPI *qspiSFR = handle->qspi;
1164  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
1165 
1166  IfxDma_ChannelId txDmaChannelId = handle->dma.txDmaChannelId;
1167  IfxDma_ChannelId rxDmaChannelId = handle->dma.rxDmaChannelId;
1168 
1169  boolean interruptState = IfxCpu_disableInterrupts();
1170 
1171  {
1172  IfxDma_setChannelTransferCount(dmaSFR, txDmaChannelId, fifosize);
1173 
1175 
1176  {
1177  IfxDma_setChannelSourceAddress(dmaSFR, txDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), job->data));
1180  /* maybe circular buffering was enabled by other call, we disable the circular buffering */
1181  /* we must do this direct why we don't have function for this */
1182  dmaSFR->CH[txDmaChannelId].ADICR.B.SCBE = FALSE;
1183 
1184  if (chHandle->mode != IfxQspi_SpiMaster_Mode_xxl)
1185  {
1186  IfxDma_setChannelDestinationAddress(dmaSFR, txDmaChannelId, (uint32 *)&qspiSFR->MIXENTRY.U);
1189  }
1190  }
1191 
1192  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
1193  }
1194 
1195  /* Receive config */
1196  IfxDma_setChannelTransferCount(dmaSFR, rxDmaChannelId, IFXQSPI_FIFO32BITSIZE(job->remaining));
1198 
1199  if (chHandle->base.rx.data == NULL_PTR)
1200  {
1201  IfxDma_setChannelDestinationAddress(dmaSFR, rxDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), &IfxQspi_SpiMaster_dummyRxValue));
1204  /* need to enable circular buffering to avoid increment higher than 4 bytes */
1205  /* we must do this direct why we don't have function for this */
1206  dmaSFR->CH[rxDmaChannelId].ADICR.B.DCBE = TRUE;
1207  }
1208  else
1209  {
1210  IfxDma_setChannelDestinationAddress(dmaSFR, rxDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), chHandle->base.rx.data));
1213  /* maybe circular buffering was enabled by other call, we disable the circular buffering */
1214  /* we must do this direct why we don't have function for this */
1215  dmaSFR->CH[rxDmaChannelId].ADICR.B.DCBE = FALSE;
1216  }
1217 
1218  IfxDma_clearChannelInterrupt(dmaSFR, rxDmaChannelId);
1219  IfxQspi_clearAllEventFlags(qspiSFR);
1220  src = IfxQspi_getTransmitSrc(qspiSFR);
1221  IfxSrc_clearRequest(src);
1222  src = IfxQspi_getReceiveSrc(qspiSFR);
1223  IfxSrc_clearRequest(src);
1224  src = IfxQspi_getErrorSrc(qspiSFR);
1225  IfxSrc_clearRequest(src);
1226  IfxDma_clearChannelInterrupt(dmaSFR, rxDmaChannelId);
1227  IfxDma_enableChannelTransaction(dmaSFR, rxDmaChannelId);
1228 
1230  {
1231  (job->remaining >= 16) ? (chHandle->bacon.B.DL = 16 - 1) : (chHandle->bacon.B.DL = job->remaining - 1);
1232  (job->remaining >= 16) ? (chHandle->bacon.B.LAST = 0) : (chHandle->bacon.B.LAST = 1);
1233  chHandle->bacon.B.BYTE = 1;
1234  }
1235  else if (chHandle->mode == IfxQspi_SpiMaster_Mode_long)
1236  {
1237  (job->remaining >= 16) ? (chHandle->bacon.B.DL = 16 - 1) : (chHandle->bacon.B.DL = job->remaining - 1);
1238  chHandle->bacon.B.LAST = 1;
1239  chHandle->bacon.B.BYTE = 1;
1240  }
1241  else
1242  {
1243  chHandle->bacon.B.LAST = 1;
1244  chHandle->bacon.B.BYTE = 1;
1245  chHandle->bacon.B.DL = 0;
1246  }
1247 
1248  {
1249  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
1250  IfxDma_enableChannelTransaction(dmaSFR, txDmaChannelId);
1251  }
1252 
1253  if (chHandle->mode != IfxQspi_SpiMaster_Mode_xxl)
1254  {
1255  qspiSFR->MIXENTRY.U = chHandle->bacon.U;
1256  }
1257  else
1258  {
1259  qspiSFR->BACONENTRY.U = chHandle->bacon.U;
1260  }
1261 
1262  IfxCpu_restoreInterrupts(interruptState);
1263  }
1264  else
1265  {
1267  }
1268 }