iLLD_TC27xC  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_0_1_0_10
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 sets Auto SLSO.
60  * \param chHandle Module Channel handle
61  * \return None
62  */
63 static void IfxQspi_SpiMaster_autoSlso(IfxQspi_SpiMaster_Channel *chHandle);
64 
65 /** \brief Deactive the SLSO pin.
66  * \param chHandle Module Channel handle
67  * \return None
68  */
69 static void IfxQspi_SpiMaster_deactivateSlso(IfxQspi_SpiMaster_Channel *chHandle);
70 
71 /** \brief Locks the transfer and gets the current status of it.
72  * \param handle Module handle
73  * \return SpiIf_Status_ok if sending is done otherwise SpiIf_Status_busy.
74  */
75 static SpiIf_Status IfxQspi_SpiMaster_lock(IfxQspi_SpiMaster *handle);
76 
77 /** \brief Reads data from the Rx FIFO
78  * \param chHandle Module Channel handle
79  * \return None
80  */
81 static void IfxQspi_SpiMaster_read(IfxQspi_SpiMaster_Channel *chHandle);
82 
83 /** \brief Unlocks the transfers
84  * \param handle Module handle
85  * \return None
86  */
87 static void IfxQspi_SpiMaster_unlock(IfxQspi_SpiMaster *handle);
88 
89 /** \brief Writes data into the Tx FIFO
90  * \param chHandle Module Channel handle
91  * \return None
92  */
93 static void IfxQspi_SpiMaster_write(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_autoSlso(IfxQspi_SpiMaster_Channel *chHandle)
132 {}
133 
134 
135 static void IfxQspi_SpiMaster_deactivateSlso(IfxQspi_SpiMaster_Channel *chHandle)
136 {
138  IfxPort_setPinState(chHandle->slso.port, chHandle->slso.pinIndex, action);
139 }
140 
141 
142 SpiIf_Status IfxQspi_SpiMaster_exchange(IfxQspi_SpiMaster_Channel *chHandle, const void *src, void *dest, Ifx_SizeT count)
143 {
144  IfxQspi_SpiMaster *handle = (IfxQspi_SpiMaster *)chHandle->base.driver;
145  SpiIf_Status status = IfxQspi_SpiMaster_lock(handle);
146 
147  if (status == SpiIf_Status_ok)
148  {
149  /* initiate transfer when resource is free */
150  handle->base.activeChannel = &chHandle->base;
151  chHandle->base.flags.onTransfer = 1;
152  chHandle->base.tx.data = (void *)src;
153  chHandle->base.tx.remaining = count;
154  chHandle->firstWrite = TRUE;
155  chHandle->base.rx.data = dest;
156  chHandle->base.rx.remaining = count;
157 
158  if (chHandle->activateSlso != NULL_PTR)
159  {
160  chHandle->activateSlso(chHandle);
161  }
162 
163  chHandle->base.txHandler(handle->base.activeChannel);
164  }
165 
166  return status;
167 }
168 
169 
171 {
172  SpiIf_Status status = SpiIf_Status_ok;
173 
174  if ((chHandle->base.flags.onTransfer != 0) || (chHandle->base.driver->sending != 0))
175  {
176  status = SpiIf_Status_busy;
177  }
178 
179  return status;
180 }
181 
182 
184 {
185  IfxQspi_SpiMaster *handle = chConfig->base.driver->driver;
186  Ifx_QSPI *qspiSFR = handle->qspi;
187 
188  chHandle->base.driver = chConfig->base.driver;
189  chHandle->channelId = (IfxQspi_ChannelId)chConfig->sls.output.pin->slsoNr;
190  chHandle->base.flags.onTransfer = FALSE;
191  //Loop back configuration.
192  qspiSFR->GLOBALCON.B.LB = chConfig->base.mode.loopback;
193  uint8 cs = chHandle->channelId % 8;
194 
195  {
196  qspiSFR->ECON[cs].U = IfxQspi_calculateExtendedConfigurationValue(qspiSFR, cs, &chConfig->base);
197  chHandle->bacon.U = IfxQspi_calculateBasicConfigurationValue(qspiSFR, chHandle->channelId, &chConfig->base.mode, chConfig->base.baudrate);
198 
199  { /* QSPI chip-select line */
200  uint32 mask = 1U << chHandle->channelId;
201  uint32 oen = mask << 16;
202  uint32 aol = ((chConfig->base.mode.csActiveLevel == Ifx_ActiveState_low) ? 0 : 1);
203  __ldmst(&qspiSFR->SSOC.U, (mask | (mask << 16)), (aol | oen));
204  }
205  }
206  chHandle->base.baudrate = IfxQspi_calcRealBaudrate(qspiSFR, (chHandle->bacon.B.CS & 0x7U));
207 
208  /* chip-select output pin */
209  const IfxQspi_Slso_Out *slso = chConfig->sls.output.pin;
210  chHandle->slso = slso->pin;
211  chHandle->slsoActiveState = chConfig->base.mode.csActiveLevel;
212 
213  if (chHandle->slso.port == NULL_PTR)
214  {
215  chHandle->activateSlso = NULL_PTR;
216  chHandle->deactivateSlso = NULL_PTR;
217  }
218  else
219  {
220  if (!chConfig->base.mode.autoCS)
221  {
222  chHandle->activateSlso = &IfxQspi_SpiMaster_activateSlso;
223  chHandle->deactivateSlso = &IfxQspi_SpiMaster_deactivateSlso;
224 
225  /** - Override the SLSO manually as general-purpose output */
226  chHandle->deactivateSlso(chHandle);
227  IfxQspi_initSlso(slso, chConfig->sls.output.mode, chConfig->sls.output.driver, IfxPort_OutputIdx_general);
228  }
229  else
230  {
231  chHandle->activateSlso = &IfxQspi_SpiMaster_autoSlso;
232  chHandle->deactivateSlso = &IfxQspi_SpiMaster_autoSlso;
233  IfxQspi_initSlso(slso, chConfig->sls.output.mode, chConfig->sls.output.driver, slso->select);
234  }
235  }
236 
237  chHandle->dataWidth = chConfig->base.mode.dataWidth;
238  chHandle->base.txHandler = (TxRxHandler) & IfxQspi_SpiMaster_write;
239  chHandle->base.rxHandler = (TxRxHandler) & IfxQspi_SpiMaster_read;
240 
241  if (handle->dma.useDma)
242  {
243  Ifx_DMA *dmaSFR = &MODULE_DMA;
244  IfxDma_setChannelDestinationAddress(dmaSFR, handle->dma.txDmaChannelId, (uint32 *)&qspiSFR->DATAENTRY[cs].U);
245  }
246 
247  return SpiIf_Status_ok;
248 }
249 
250 
252 {
253  SpiIf_initChannelConfig(&chConfig->base, &handle->base);
254  chConfig->sls.output.pin = NULL_PTR;
257  chConfig->sls.input.pin = NULL_PTR;
259 }
260 
261 
263 {
264  Ifx_QSPI *qspiSFR = config->qspi;
265 
266  Ifx_DMA *dmaSFR = &MODULE_DMA;
267 
268  /* handle.base must be at offset 0 to be compatible with the standard interface SscIf */
269  {
271  IfxScuWdt_clearCpuEndinit(password);
274  IfxScuWdt_setCpuEndinit(password);
275  }
276 
277  { /* Configure GLOBAL, Note: at the moment default values for GLOBAL */
278  Ifx_QSPI_GLOBALCON globalcon;
279  globalcon.U = 0;
280  globalcon.B.TQ = IfxQspi_calculateTimeQuantumLength(qspiSFR, config->base.maximumBaudrate);
281  globalcon.B.EXPECT = IfxQspi_ExpectTimeout_2097152; /* 2^(EXPECT+6) : timeout for expect phase in Tqspi */
282  //globalcon.B.LB = 0 ; /* 0 : disable loop-back w*/
283  //globalcon.B.DEL0 = 0; /* 0 : disable delayed mode for SLSO 0 */
284  //globalcon.B.STROBE = 0; /* (STROBE+1) : strobe delay for SLSO 0 in Tq */
285  //globalcon.B.SRF = 0; /* 0 : disable stop-on-RXFIFO full feature */
286  //globalcon.B.STIP = 0; /* 0 : MRST = 0 when QSPI is deselected in slave mode */
287  //globalcon.B.EN = 0; /* 0 : PAUSE requested, 1 : RUN requested */
288  globalcon.B.MS = IfxQspi_Mode_master; /* select master mode */
289  globalcon.B.AREN = (config->pauseOnBaudrateSpikeErrors != FALSE) ? 1U : 0U;
290  globalcon.B.RESETS = 1;
291  qspiSFR->GLOBALCON.U = globalcon.U;
292  }
293 
294  { /* Configure interrupt requests */
295  Ifx_QSPI_GLOBALCON1 globalcon1;
296  globalcon1.U = 0;
297  //TODO: globalcon1.B.ERRORENS;
298  globalcon1.B.TXEN = (config->base.txPriority > 0) || (config->dma.useDma);
299  globalcon1.B.RXEN = (config->base.rxPriority > 0) || (config->dma.useDma);
300  globalcon1.B.TXFIFOINT = config->txFifoThreshold;
301  globalcon1.B.RXFIFOINT = config->rxFifoThreshold;
302  qspiSFR->GLOBALCON1.U = globalcon1.U;
303  }
304 
305  /* Configure I/O pins for master mode */
306  const IfxQspi_SpiMaster_Pins *pins = config->pins;
307 
308  if (pins != NULL_PTR)
309  {
310  const IfxQspi_Sclk_Out *sclkOut = pins->sclk;
311 
312  if (sclkOut != NULL_PTR)
313  {
314  IfxQspi_initSclkOutPin(sclkOut, pins->sclkMode, pins->pinDriver);
315  }
316 
317  const IfxQspi_Mtsr_Out *mtsrOut = pins->mtsr;
318 
319  if (mtsrOut != NULL_PTR)
320  {
321  IfxQspi_initMtsrOutPin(mtsrOut, pins->mtsrMode, pins->pinDriver);
322  }
323 
324  const IfxQspi_Mrst_In *mrstIn = pins->mrst;
325 
326  if (mrstIn != NULL_PTR)
327  {
328  IfxQspi_initMrstInPin(mrstIn, pins->mrstMode);
329  }
330  }
331 
332  handle->qspi = qspiSFR;
333  handle->base.driver = handle;
334  handle->base.sending = 0U;
335  handle->base.activeChannel = NULL_PTR;
336 
339 
340  if (config->dma.useDma)
341  {
344  }
345  else
346  {
349  }
350 
352 
353  if (config->dma.useDma)
354  {
355  handle->dma.useDma = TRUE;
356  IfxDma_Dma dma;
357  IfxDma_Dma_createModuleHandle(&dma, dmaSFR);
358 
360  IfxDma_Dma_initChannelConfig(&dmaCfg, &dma);
361 
362  {
363  handle->dma.txDmaChannelId = config->dma.txDmaChannelId;
364  dmaCfg.channelId = handle->dma.txDmaChannelId;
365  dmaCfg.hardwareRequestEnabled = FALSE; // will be triggered from FFT service request
366  dmaCfg.channelInterruptEnabled = TRUE; // trigger interrupt after transaction
367 
368  // source address and transfer count will be configured during runtime
369  dmaCfg.sourceAddress = 0;
372  dmaCfg.transferCount = 0;
374 
375  // destination address is fixed; use circular mode to stay at this address for each move
376  dmaCfg.destinationAddress = (uint32)&qspiSFR->DATAENTRY[0].U;
379 
383 
384  IfxDma_Dma_initChannel(&handle->dma.txDmaChannel, &dmaCfg);
385  }
386 
387  {
388  handle->dma.rxDmaChannelId = config->dma.rxDmaChannelId;
389  dmaCfg.channelId = handle->dma.rxDmaChannelId;
390  dmaCfg.hardwareRequestEnabled = FALSE; // will be triggered from qspi service request
391  dmaCfg.channelInterruptEnabled = TRUE; // trigger interrupt after transaction
392 
393  // source address is fixed; use circular mode to stay at this address for each move
394  dmaCfg.sourceAddress = (uint32)&qspiSFR->RXEXIT.U;
397 
398  // destination address and transfer count will be configured during runtime
399  dmaCfg.destinationAddress = 0;
402  dmaCfg.transferCount = 0;
403 
408 
409  IfxDma_Dma_initChannel(&handle->dma.rxDmaChannel, &dmaCfg);
410  }
411  /* Dma channel interrupt configuration */
412  {
413  volatile Ifx_SRC_SRCR *src = IfxDma_getSrcPointer(dmaSFR, (IfxDma_ChannelId)config->dma.txDmaChannelId);
415  IfxSrc_enable(src);
416 
419  IfxSrc_enable(src);
420  }
421  }
422 
423  /* Qspi interrupt configuration */
424  {
425  /** NOTE: If not DMA, the interrupt service provider is assigned to the CPU ID where
426  * this function is called from */
427 
429 
430  if (handle->dma.useDma)
431  {
432  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
434  IfxSrc_enable(src);
435 
436  src = IfxQspi_getReceiveSrc(qspiSFR);
438  IfxSrc_enable(src);
439  }
440  else
441  {
442  if (config->base.txPriority != 0)
443  {
444  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
445  IfxSrc_init(src, config->base.isrProvider, config->base.txPriority);
446  IfxSrc_enable(src);
447  }
448 
449  if (config->base.rxPriority != 0)
450  {
451  volatile Ifx_SRC_SRCR *src = IfxQspi_getReceiveSrc(qspiSFR);
452  IfxSrc_init(src, config->base.isrProvider, config->base.rxPriority);
453  IfxSrc_enable(src);
454  }
455  }
456  }
457 
458  IfxQspi_run(qspiSFR);
459 }
460 
461 
463 {
464  SpiIf_initConfig(&config->base);
465  config->qspi = qspi;
466  config->allowSleepMode = FALSE;
471  config->pins = NULL_PTR;
474  config->dma.useDma = FALSE;
475 }
476 
477 
479 {
480  Ifx_DMA *dmaSFR = &MODULE_DMA;
481  IfxDma_ChannelId rxDmaChannelId = qspiHandle->dma.rxDmaChannelId;
482  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(qspiHandle);
483 
484  if (IfxDma_getAndClearChannelInterrupt(dmaSFR, rxDmaChannelId))
485  {
486  if (chHandle->deactivateSlso != NULL_PTR)
487  {
488  chHandle->deactivateSlso(chHandle);
489  }
490 
491  chHandle->base.flags.onTransfer = 0;
492  IfxQspi_SpiMaster_unlock((IfxQspi_SpiMaster *)chHandle->base.driver);
493  }
494 
496 }
497 
498 
500 {
501  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(qspiHandle);
502  SpiIf_Job *job = &chHandle->base.tx;
503  Ifx_DMA *dmaSFR = &MODULE_DMA;
504  IfxDma_ChannelId txDmaChannelId = qspiHandle->dma.txDmaChannelId;
505 
506  Ifx_QSPI *qspiSFR = qspiHandle->qspi;
507  uint8 cs = chHandle->bacon.B.CS;
508 
509  if (IfxDma_getAndClearChannelPatternDetectionInterrupt(dmaSFR, txDmaChannelId))
510  {
511  // DMA_TC.031 workaround ..
512  IfxDma_getAndClearChannelInterrupt(dmaSFR, txDmaChannelId);
513  }
514  else if (IfxDma_getAndClearChannelInterrupt(dmaSFR, txDmaChannelId) && (job->remaining > 1))
515  {
516  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
517  IfxDma_disableChannelTransaction(dmaSFR, txDmaChannelId);
518 
519  if (job->data == NULL_PTR)
520  {
521  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
522  IfxQspi_writeTransmitFifo(qspiSFR, cs, ~0);
523  }
524  else
525  {
526  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
527 
528  if (chHandle->dataWidth <= 8)
529  {
530  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint8 *)job->data)[job->remaining - 1]);
531  }
532  else if (chHandle->dataWidth <= 16)
533  {
534  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint16 *)job->data)[job->remaining - 1]);
535  }
536  else
537  {
538  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint32 *)job->data)[job->remaining - 1]);
539  }
540  }
541  }
542 }
543 
544 
546 {
547  // FIXME implement error handler
548  Ifx_QSPI *qspiSFR = handle->qspi;
550 }
551 
552 
554 {
555  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(handle);
556  chHandle->base.rxHandler(&chHandle->base);
557  handle->base.rxCount++;
558 }
559 
560 
562 {
563  IfxQspi_SpiMaster_Channel *chHandle = IfxQspi_SpiMaster_activeChannel(handle);
564  chHandle->base.txHandler(&chHandle->base);
565  handle->base.txCount++;
566 }
567 
568 
569 static SpiIf_Status IfxQspi_SpiMaster_lock(IfxQspi_SpiMaster *handle)
570 {
571  sint32 sending = __swap(&handle->base.sending, 1UL);
572  return (sending == 0) ? SpiIf_Status_ok : SpiIf_Status_busy;
573 }
574 
575 
576 static void IfxQspi_SpiMaster_read(IfxQspi_SpiMaster_Channel *chHandle)
577 {
578  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
579  Ifx_QSPI *qspiSFR = handle->qspi;
580  SpiIf_Job *job = &chHandle->base.rx;
581 
583  count = __min(job->remaining, count);
584 
585  if (job->data == NULL_PTR)
586  {
587  // no data should be buffered: do dummy reads
588  int i;
589 
590  for (i = 0; i < count; ++i)
591  {
592  IfxQspi_readReceiveFifo(qspiSFR);
593  }
594  }
595  else
596  {
597  if (chHandle->dataWidth <= 8)
598  {
599  IfxQspi_read8(qspiSFR, job->data, count);
600  job->data = &(((uint8 *)job->data)[count]);
601  }
602  else if (chHandle->dataWidth <= 16)
603  {
604  IfxQspi_read16(qspiSFR, job->data, count);
605  job->data = &(((uint16 *)job->data)[count]);
606  }
607  else
608  {
609  IfxQspi_read32(qspiSFR, job->data, count);
610  job->data = &(((uint32 *)job->data)[count]);
611  }
612  }
613 
614  job->remaining = job->remaining - count;
615 
616  if (job->remaining == 0)
617  {
618  if (chHandle->deactivateSlso != NULL_PTR)
619  {
620  chHandle->deactivateSlso(chHandle);
621  }
622 
623  chHandle->base.flags.onTransfer = 0;
624  IfxQspi_SpiMaster_unlock((IfxQspi_SpiMaster *)chHandle->base.driver);
625  }
626 }
627 
628 
629 static void IfxQspi_SpiMaster_unlock(IfxQspi_SpiMaster *handle)
630 {
631  handle->base.sending = 0UL;
632 }
633 
634 
635 static void IfxQspi_SpiMaster_write(IfxQspi_SpiMaster_Channel *chHandle)
636 {
637  SpiIf_Job *job = &chHandle->base.tx;
638  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
639 
640  if (handle->dma.useDma)
641  {
642  Ifx_DMA *dmaSFR = &MODULE_DMA;
643 
644  Ifx_QSPI *qspiSFR = handle->qspi;
645  volatile Ifx_SRC_SRCR *src = IfxQspi_getTransmitSrc(qspiSFR);
646 
647  IfxDma_ChannelId txDmaChannelId = handle->dma.txDmaChannelId;
648  IfxDma_ChannelId rxDmaChannelId = handle->dma.rxDmaChannelId;
649 
650  boolean interruptState = IfxCpu_disableInterrupts();
651 
652  if (job->remaining > 1)
653  {
654  IfxDma_setChannelTransferCount(dmaSFR, txDmaChannelId, job->remaining - 1);
655 
656  if (chHandle->dataWidth <= 8)
657  {
659  }
660  else if (chHandle->dataWidth <= 16)
661  {
663  }
664  else
665  {
667  }
668 
669  if (job->data == NULL_PTR)
670  {
671  IfxDma_setChannelSourceAddress(dmaSFR, txDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), &IfxQspi_SpiMaster_dummyTxValue));
674  }
675  else
676  {
677  IfxDma_setChannelSourceAddress(dmaSFR, txDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), job->data));
680  }
681 
682  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
683  }
684 
685  /* Receive config */
686  IfxDma_setChannelTransferCount(dmaSFR, rxDmaChannelId, job->remaining);
687 
688  if (chHandle->dataWidth <= 8)
689  {
691  }
692  else if (chHandle->dataWidth <= 16)
693  {
695  }
696  else
697  {
699  }
700 
701  if (chHandle->base.rx.data == NULL_PTR)
702  {
703  IfxDma_setChannelDestinationAddress(dmaSFR, rxDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), &IfxQspi_SpiMaster_dummyRxValue));
706  }
707  else
708  {
709  IfxDma_setChannelDestinationAddress(dmaSFR, rxDmaChannelId, (void *)IFXCPU_GLB_ADDR_DSPR(IfxCpu_getCoreId(), chHandle->base.rx.data));
712  }
713 
714  IfxDma_clearChannelInterrupt(dmaSFR, rxDmaChannelId);
715 
716  IfxQspi_flushTransmitFifo(qspiSFR);
717  IfxQspi_flushReceiveFifo(qspiSFR);
719  src = IfxQspi_getTransmitSrc(qspiSFR);
720  IfxSrc_clearRequest(src);
721  src = IfxQspi_getReceiveSrc(qspiSFR);
722  IfxSrc_clearRequest(src);
723  src = IfxQspi_getErrorSrc(qspiSFR);
724  IfxSrc_clearRequest(src);
725  IfxDma_clearChannelInterrupt(dmaSFR, rxDmaChannelId);
726  IfxDma_setChannelInterruptServiceRequest(dmaSFR, rxDmaChannelId);
727  IfxDma_enableChannelTransaction(dmaSFR, rxDmaChannelId);
728 
729  if (job->remaining > 1)
730  {
731  IfxDma_clearChannelInterrupt(dmaSFR, txDmaChannelId);
732  IfxDma_setChannelInterruptServiceRequest(dmaSFR, txDmaChannelId);
733 
734  IfxDma_enableChannelTransaction(dmaSFR, txDmaChannelId);
736  IfxDma_startChannelTransaction(dmaSFR, txDmaChannelId);
737  }
738  else
739  {
740  uint8 cs = chHandle->bacon.B.CS;
741 
742  if (job->data == NULL_PTR)
743  {
744  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
745  IfxQspi_writeTransmitFifo(qspiSFR, cs, ~0);
746  }
747  else
748  {
749  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
750 
751  if (chHandle->dataWidth <= 8)
752  {
753  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint8 *)job->data)[job->remaining - 1]);
754  }
755  else if (chHandle->dataWidth <= 16)
756  {
757  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint16 *)job->data)[job->remaining - 1]);
758  }
759  else
760  {
761  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint32 *)job->data)[job->remaining - 1]);
762  }
763  }
764  }
765 
766  IfxCpu_restoreInterrupts(interruptState);
767  }
768  else
769  {
770  if (job->remaining > 0)
771  {
772  IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
773  Ifx_QSPI *qspiSFR = handle->qspi;
774  uint8 cs = chHandle->bacon.B.CS;
775 
776  // following operation must be atomic (FIXME actually, we would only have to stall the Tx interrupt)
777  boolean interruptState = IfxCpu_disableInterrupts();
778  Ifx_SizeT count = (Ifx_SizeT)(IFXQSPI_CFG_HWFIFO_DEPTH - 1 - IfxQspi_getTransmitFifoLevel(qspiSFR)); // -1, since BACON allocates one FIFO entry
779  count = __min(job->remaining, count);
780 
781  if (count > 0)
782  {
783  job->remaining = job->remaining - count;
784 
785  // push BACON into FIFO before first data word
786  if (chHandle->firstWrite == TRUE)
787  {
788  chHandle->firstWrite = FALSE;
790  }
791 
792  // we have to push another BACON into FIFO before the last data word
793  boolean lastWrite = job->remaining == 0;
794 
795  if (job->data == NULL_PTR)
796  {
797  // no data should be sent (only received): send all-1
798  int i;
799 
800  if (lastWrite)
801  {
802  for (i = 0; i < count - 1; ++i)
803  {
804  IfxQspi_writeTransmitFifo(qspiSFR, cs, ~0);
805  }
806 
807  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
808  IfxQspi_writeTransmitFifo(qspiSFR, cs, ~0);
809  }
810  else
811  {
812  for (i = 0; i < count; ++i)
813  {
814  IfxQspi_writeTransmitFifo(qspiSFR, cs, ~0);
815  }
816  }
817  }
818  else
819  {
820  if (chHandle->dataWidth <= 8)
821  {
822  if (lastWrite)
823  {
824  if (count >= 2)
825  {
826  IfxQspi_write8(qspiSFR, cs, job->data, count - 1);
827  }
828 
829  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
830  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint8 *)job->data)[count - 1]);
831  }
832  else
833  {
834  IfxQspi_write8(qspiSFR, cs, job->data, count);
835  }
836 
837  job->data = &(((uint8 *)job->data)[count]);
838  }
839  else if (chHandle->dataWidth <= 16)
840  {
841  if (lastWrite)
842  {
843  if (count >= 2)
844  {
845  IfxQspi_write16(qspiSFR, cs, job->data, count - 1);
846  }
847 
848  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
849  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint16 *)job->data)[count - 1]);
850  }
851  else
852  {
853  IfxQspi_write16(qspiSFR, cs, job->data, count);
854  job->data = &(((uint16 *)job->data)[count]);
855  }
856  }
857  else
858  {
859  if (lastWrite)
860  {
861  if (count >= 2)
862  {
863  IfxQspi_write32(qspiSFR, cs, job->data, count - 1);
864  }
865 
866  IfxQspi_writeBasicConfigurationEndStream(qspiSFR, chHandle->bacon.U);
867  IfxQspi_writeTransmitFifo(qspiSFR, cs, ((uint32 *)job->data)[count - 1]);
868  }
869  else
870  {
871  IfxQspi_write32(qspiSFR, cs, job->data, count);
872  job->data = &(((uint32 *)job->data)[count]);
873  }
874  }
875  }
876  }
877 
878  IfxCpu_restoreInterrupts(interruptState);
879  }
880  }
881 }