flexio_spi_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
19 #include "flexio_spi_driver.h"
20 #include "flexio_hw_access.h"
21 #include "flexio_common.h"
22 #include "clock_manager.h"
23 
77 /*******************************************************************************
78  * Variables
79  ******************************************************************************/
80 
83  /* Constraints used for baud rate computation */
84 #define DIVIDER_MIN_VALUE 1U
85 #define DIVIDER_MAX_VALUE 0xFFU
86 
87  /* Shifters/Timers used for SPI simulation. The parameter x represents the
88  resourceIndex value for the current driver instance */
89 #define TX_SHIFTER(x) (x)
90 #define RX_SHIFTER(x) (uint8_t)((x) + 1U)
91 #define SCK_TIMER(x) (x)
92 #define SS_TIMER(x) (uint8_t)((x) + 1U)
93 
94  /* Dummy data to send when user provides no data */
95 #define FLEXIO_SPI_DUMMYDATA (0xFFFFFFFFU)
96 
97 /*******************************************************************************
98  * Private Functions
99  ******************************************************************************/
100 
101 /*FUNCTION**********************************************************************
102  *
103  * Function Name : FLEXIO_SPI_DRV_MasterComputeBaudRateDivider
104  * Description : Computes the baud rate divider for a target baud rate
105  *
106  *END**************************************************************************/
107 static void FLEXIO_SPI_DRV_MasterComputeBaudRateDivider(uint32_t baudRate,
108  uint16_t *divider,
109  uint32_t inputClock)
110 {
111  uint32_t tmpDiv;
112 
113  /* Compute divider: ((input_clock / baud_rate) / 2) - 1. Round to nearest integer */
114  tmpDiv = ((inputClock + baudRate) / (2U * baudRate)) - 1U;
115  /* Enforce upper/lower limits */
116  if (tmpDiv < DIVIDER_MIN_VALUE)
117  {
118  tmpDiv = DIVIDER_MIN_VALUE;
119  }
120  if (tmpDiv > DIVIDER_MAX_VALUE)
121  {
122  tmpDiv = DIVIDER_MAX_VALUE;
123  }
124 
125  *divider = (uint16_t)tmpDiv;
126 }
127 
128 
129 /*FUNCTION**********************************************************************
130  *
131  * Function Name : FLEXIO_SPI_DRV_MasterConfigure
132  * Description : configures the FLEXIO module as SPI master
133  *
134  *END**************************************************************************/
135 static void FLEXIO_SPI_DRV_MasterConfigure(const flexio_spi_master_state_t *master,
136  const flexio_spi_master_user_config_t * userConfigPtr,
137  uint32_t inputClock)
138 {
139  FLEXIO_Type *baseAddr;
140  flexio_pin_polarity_t clockPolarity; /* Polarity of clock signal */
141  flexio_timer_polarity_t txShifterPolarity; /* Polarity of MOSI shifter */
142  flexio_timer_polarity_t rxShifterPolarity; /* Polarity of MISO shifter */
143  uint16_t divider;
144  flexio_shifter_stop_t stopBit;
145  flexio_shifter_start_t startBit;
146  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
147 
148  baseAddr = g_flexioBase[master->flexioCommon.instance];
149  resourceIndex = master->flexioCommon.resourceIndex;
150  /* Compute divider.*/
151  FLEXIO_SPI_DRV_MasterComputeBaudRateDivider(userConfigPtr->baudRate, &divider, inputClock);
152  /* add number of bits in the upper 8 bits of the divider. Formula is: TIMCMP[15:8] = (number of bits x 2) - 1 */
153  divider += (uint16_t)((((uint16_t)(userConfigPtr->transferSize) * 8U * 2U) - 1U) << 8U);
154 
155  if (userConfigPtr->clockPolarity == 0U)
156  {
157  /* CPOL = 0 */
158  clockPolarity = FLEXIO_PIN_POLARITY_HIGH;
159  }
160  else
161  {
162  /* CPOL = 1 */
163  clockPolarity = FLEXIO_PIN_POLARITY_LOW;
164  }
165 
166  if (userConfigPtr->clockPhase == 0U)
167  {
168  /* CPHA = 0 */
169  txShifterPolarity = FLEXIO_TIMER_POLARITY_NEGEDGE;
170  rxShifterPolarity = FLEXIO_TIMER_POLARITY_POSEDGE;
171  stopBit = FLEXIO_SHIFTER_STOP_BIT_DISABLED;
172  startBit = FLEXIO_SHIFTER_START_BIT_DISABLED;
173  }
174  else
175  {
176  /* CPHA = 1 */
177  txShifterPolarity = FLEXIO_TIMER_POLARITY_POSEDGE;
178  rxShifterPolarity = FLEXIO_TIMER_POLARITY_NEGEDGE;
179  stopBit = FLEXIO_SHIFTER_STOP_BIT_0;
180  startBit = FLEXIO_SHIFTER_START_BIT_DISABLED_SH;
181  }
182 
183  /* Configure Tx shifter (MOSI) */
184  FLEXIO_SetShifterControl(baseAddr,
185  TX_SHIFTER(resourceIndex),
186  FLEXIO_SHIFTER_MODE_DISABLED,
187  userConfigPtr->mosiPin,
188  FLEXIO_PIN_POLARITY_HIGH,
189  FLEXIO_PIN_CONFIG_OUTPUT,
190  SCK_TIMER(resourceIndex),
191  txShifterPolarity);
192  FLEXIO_SetShifterConfig(baseAddr,
193  TX_SHIFTER(resourceIndex),
194  startBit,
195  stopBit,
196  FLEXIO_SHIFTER_SOURCE_PIN);
197 
198  /* Configure Rx shifter (MISO) */
199  FLEXIO_SetShifterControl(baseAddr,
200  RX_SHIFTER(resourceIndex),
201  FLEXIO_SHIFTER_MODE_DISABLED,
202  userConfigPtr->misoPin,
203  FLEXIO_PIN_POLARITY_HIGH,
204  FLEXIO_PIN_CONFIG_DISABLED,
205  SCK_TIMER(resourceIndex),
206  rxShifterPolarity);
207  FLEXIO_SetShifterConfig(baseAddr,
208  RX_SHIFTER(resourceIndex),
209  FLEXIO_SHIFTER_START_BIT_DISABLED,
210  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
211  FLEXIO_SHIFTER_SOURCE_PIN);
212 
213  /* Configure sck timer */
214  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), divider); /* set baud rate, and number of bits */
215  FLEXIO_SetTimerConfig(baseAddr,
216  SCK_TIMER(resourceIndex),
217  FLEXIO_TIMER_START_BIT_ENABLED,
218  FLEXIO_TIMER_STOP_BIT_TIM_DIS,
219  FLEXIO_TIMER_ENABLE_TRG_HIGH,
220  FLEXIO_TIMER_DISABLE_TIM_CMP,
221  FLEXIO_TIMER_RESET_NEVER,
222  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR,
223  FLEXIO_TIMER_INITOUT_ZERO);
224  FLEXIO_SetTimerControl(baseAddr,
225  SCK_TIMER(resourceIndex),
226  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
227  FLEXIO_TRIGGER_POLARITY_LOW,
228  FLEXIO_TRIGGER_SOURCE_INTERNAL,
229  userConfigPtr->sckPin, /* output on clock pin */
230  clockPolarity, /* used configured polarity */
231  FLEXIO_PIN_CONFIG_OUTPUT,
232  FLEXIO_TIMER_MODE_DISABLED);
233 
234  /* Configure SS timer */
235  FLEXIO_SetTimerCompare(baseAddr, SS_TIMER(resourceIndex), 0xFFFFU);
236  FLEXIO_SetTimerConfig(baseAddr,
237  SS_TIMER(resourceIndex),
238  FLEXIO_TIMER_START_BIT_DISABLED,
239  FLEXIO_TIMER_STOP_BIT_DISABLED,
240  FLEXIO_TIMER_ENABLE_TIM_ENABLE, /* enable when SCK timer is enabled */
241  FLEXIO_TIMER_DISABLE_TIM_DISABLE, /* disable when SCK timer is disabled */
242  FLEXIO_TIMER_RESET_NEVER,
243  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR,
244  FLEXIO_TIMER_INITOUT_ONE);
245  FLEXIO_SetTimerControl(baseAddr,
246  SS_TIMER(resourceIndex),
247  0U, /* trigger not used, using defaults */
248  FLEXIO_TRIGGER_POLARITY_HIGH,
249  FLEXIO_TRIGGER_SOURCE_EXTERNAL,
250  userConfigPtr->ssPin,
251  FLEXIO_PIN_POLARITY_LOW,
252  FLEXIO_PIN_CONFIG_OUTPUT,
253  FLEXIO_TIMER_MODE_DISABLED);
254 }
255 
256 
257 /*FUNCTION**********************************************************************
258  *
259  * Function Name : FLEXIO_SPI_DRV_MasterEndTransfer
260  * Description : end a transfer
261  *
262  *END**************************************************************************/
263 static void FLEXIO_SPI_DRV_MasterEndTransfer(flexio_spi_master_state_t *master)
264 {
265  FLEXIO_Type *baseAddr;
266  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
267 
268  DEV_ASSERT(master != NULL);
269 
270  baseAddr = g_flexioBase[master->flexioCommon.instance];
271  resourceIndex = master->flexioCommon.resourceIndex;
272 
273  /* Disable transfer engine */
274  switch (master->driverType)
275  {
277  /* Disable interrupts for Rx and Tx shifters */
278  FLEXIO_SetShifterInterrupt(baseAddr,
279  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
280  false);
281  FLEXIO_SetShifterErrorInterrupt(baseAddr,
282  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
283  false);
284  break;
286  /* Nothing to do here */
287  break;
289  /* Stop DMA channels */
290  (void)EDMA_DRV_StopChannel(master->txDMAChannel);
291  (void)EDMA_DRV_StopChannel(master->rxDMAChannel);
292  /* Disable FlexIO DMA requests for both shifters */
293  FLEXIO_SetShifterDMARequest(baseAddr,
294  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
295  false);
296  break;
297  default:
298  /* Impossible type - do nothing */
299  break;
300  }
301 
302  master->driverIdle = true;
303  master->txRemainingBytes = 0U;
304  master->rxRemainingBytes = 0U;
305 
306  /* Signal transfer end for blocking transfers */
307  if (master->blocking == true)
308  {
309  (void)OSIF_SemaPost(&(master->idleSemaphore));
310  }
311 }
312 
313 
314 /*FUNCTION**********************************************************************
315  *
316  * Function Name : FLEXIO_SPI_DRV_MasterEnableTransfer
317  * Description : Enables timers and shifters to start a transfer
318  *
319  *END**************************************************************************/
320 static void FLEXIO_SPI_DRV_MasterEnableTransfer(flexio_spi_master_state_t *master)
321 {
322  FLEXIO_Type *baseAddr;
323  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
324 
325  resourceIndex = master->flexioCommon.resourceIndex;
326  baseAddr = g_flexioBase[master->flexioCommon.instance];
327 
328  /* enable timers and shifters */
329  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_TRANSMIT);
330  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_RECEIVE);
331  if (master->master)
332  {
333  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_8BIT_BAUD);
334  FLEXIO_SetTimerMode(baseAddr, SS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
335  }
336  else
337  {
338  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
339  }
340 }
341 
342 
343 /*FUNCTION**********************************************************************
344  *
345  * Function Name : FLEXIO_SPI_DRV_MasterStopTransfer
346  * Description : Forcefully stops the current transfer
347  *
348  *END**************************************************************************/
349 static void FLEXIO_SPI_DRV_MasterStopTransfer(flexio_spi_master_state_t *master)
350 {
351  FLEXIO_Type *baseAddr;
352  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
353 
354  resourceIndex = master->flexioCommon.resourceIndex;
355  baseAddr = g_flexioBase[master->flexioCommon.instance];
356 
357  /* disable and re-enable timers and shifters to reset them */
358  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
359  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
360  FLEXIO_SetTimerMode(baseAddr, SCK_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
361  FLEXIO_SetTimerMode(baseAddr, SS_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
362 
363  /* clear any leftover error flags */
364  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
365  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
366  /* discard any leftover rx. data */
367  FLEXIO_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
368 
369  /* end the transfer */
370  FLEXIO_SPI_DRV_MasterEndTransfer(master);
371 }
372 
373 
374 /*FUNCTION**********************************************************************
375  *
376  * Function Name : FLEXIO_SPI_DRV_MasterWaitTransferEnd
377  * Description : waits for the end of a blocking transfer
378  *
379  *END**************************************************************************/
380 static status_t FLEXIO_SPI_DRV_MasterWaitTransferEnd(flexio_spi_master_state_t *master, uint32_t timeout)
381 {
382  status_t osifError = STATUS_SUCCESS;
383 
384  DEV_ASSERT(master != NULL);
385 
386  switch (master->driverType)
387  {
389  /* Wait for transfer to be completed by the IRQ */
390  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
391  break;
393  /* Call FLEXIO_SPI_DRV_MasterGetStatus() to do the transfer */
394  while (FLEXIO_SPI_DRV_MasterGetStatus(master, NULL) == STATUS_BUSY)
395  {
396  }
397  break;
399  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
400  break;
401  default:
402  /* Impossible type - do nothing */
403  break;
404  }
405 
406  /* blocking transfer is over */
407  master->blocking = false;
408  if (osifError == STATUS_TIMEOUT)
409  {
410  /* abort current transfer */
411  master->status = STATUS_TIMEOUT;
412  FLEXIO_SPI_DRV_MasterStopTransfer(master);
413  }
414 
415  return master->status;
416 }
417 
418 
419 /*FUNCTION**********************************************************************
420  *
421  * Function Name : FLEXIO_SPI_DRV_MasterEndDmaTransfer
422  * Description : end a DMA transfer
423  *
424  *END**************************************************************************/
425 static void FLEXIO_SPI_DRV_MasterEndDmaTransfer(void *stateStruct, edma_chn_status_t status)
426 {
428 
429  DEV_ASSERT(stateStruct != NULL);
430 
431  master = (flexio_spi_master_state_t *)stateStruct;
432 
433  /* Record success if there was no error */
434  if (status == EDMA_CHN_ERROR)
435  {
436  master->status = STATUS_ERROR;
437  }
438  else
439  {
440  master->status = STATUS_SUCCESS;
441  }
442  FLEXIO_SPI_DRV_MasterStopTransfer(master);
443  /* Call callback to announce the event to the user */
444  if (master->callback != NULL)
445  {
446  master->callback(master, SPI_EVENT_END_TRANSFER, master->callbackParam);
447  }
448 }
449 
450 
451 /*FUNCTION**********************************************************************
452  *
453  * Function Name : FLEXIO_SPI_DRV_SlaveConfigure
454  * Description : configures the FLEXIO module as SPI slave
455  *
456  *END**************************************************************************/
457 static void FLEXIO_SPI_DRV_SlaveConfigure(const flexio_spi_slave_state_t *slave,
458  const flexio_spi_slave_user_config_t * userConfigPtr)
459 {
460  FLEXIO_Type *baseAddr;
461  flexio_pin_polarity_t clockPolarity; /* Polarity of clock signal */
462  flexio_timer_polarity_t txShifterPolarity; /* Polarity of MISO shifter */
463  flexio_timer_polarity_t rxShifterPolarity; /* Polarity of MOSI shifter */
464  flexio_shifter_start_t startBit;
465  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
466 
467  baseAddr = g_flexioBase[slave->flexioCommon.instance];
468  resourceIndex = slave->flexioCommon.resourceIndex;
469 
470  if (userConfigPtr->clockPolarity == 0U)
471  {
472  /* CPOL = 0 */
473  clockPolarity = FLEXIO_PIN_POLARITY_HIGH;
474  }
475  else
476  {
477  /* CPOL = 1 */
478  clockPolarity = FLEXIO_PIN_POLARITY_LOW;
479  }
480 
481  if (userConfigPtr->clockPhase == 0U)
482  {
483  /* CPHA = 0 */
484  txShifterPolarity = FLEXIO_TIMER_POLARITY_NEGEDGE;
485  rxShifterPolarity = FLEXIO_TIMER_POLARITY_POSEDGE;
486  startBit = FLEXIO_SHIFTER_START_BIT_DISABLED;
487  }
488  else
489  {
490  /* CPHA = 1 */
491  txShifterPolarity = FLEXIO_TIMER_POLARITY_POSEDGE;
492  rxShifterPolarity = FLEXIO_TIMER_POLARITY_NEGEDGE;
493  startBit = FLEXIO_SHIFTER_START_BIT_DISABLED_SH;
494  }
495 
496  /* Configure Slave Tx shifter (MISO) */
497  FLEXIO_SetShifterControl(baseAddr,
498  TX_SHIFTER(resourceIndex),
499  FLEXIO_SHIFTER_MODE_DISABLED,
500  userConfigPtr->misoPin,
501  FLEXIO_PIN_POLARITY_HIGH,
502  FLEXIO_PIN_CONFIG_OUTPUT,
503  SCK_TIMER(resourceIndex),
504  txShifterPolarity);
505  FLEXIO_SetShifterConfig(baseAddr,
506  TX_SHIFTER(resourceIndex),
507  startBit,
508  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
509  FLEXIO_SHIFTER_SOURCE_PIN);
510 
511  /* Configure Slave Rx shifter (MOSI) */
512  FLEXIO_SetShifterControl(baseAddr,
513  RX_SHIFTER(resourceIndex),
514  FLEXIO_SHIFTER_MODE_DISABLED,
515  userConfigPtr->mosiPin,
516  FLEXIO_PIN_POLARITY_HIGH,
517  FLEXIO_PIN_CONFIG_DISABLED,
518  SCK_TIMER(resourceIndex),
519  rxShifterPolarity);
520  FLEXIO_SetShifterConfig(baseAddr,
521  RX_SHIFTER(resourceIndex),
522  FLEXIO_SHIFTER_START_BIT_DISABLED,
523  FLEXIO_SHIFTER_STOP_BIT_DISABLED,
524  FLEXIO_SHIFTER_SOURCE_PIN);
525 
526  /* Configure sck timer */
527  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), 0xFFFFU);
528  FLEXIO_SetTimerConfig(baseAddr,
529  SCK_TIMER(resourceIndex),
530  FLEXIO_TIMER_START_BIT_DISABLED,
531  FLEXIO_TIMER_STOP_BIT_DISABLED,
532  FLEXIO_TIMER_ENABLE_TRG_POSEDGE, /* enable on SS pin rising edge */
533  FLEXIO_TIMER_DISABLE_TRG, /* disable on SS pin falling edge */
534  FLEXIO_TIMER_RESET_NEVER,
535  FLEXIO_TIMER_DECREMENT_PIN_SHIFT_PIN, /* decrement on input pin - SCK */
536  FLEXIO_TIMER_INITOUT_ZERO);
537  FLEXIO_SetTimerControl(baseAddr,
538  SCK_TIMER(resourceIndex),
539  (uint8_t)(userConfigPtr->ssPin << 1U), /* trigger on SS pin edge */
540  FLEXIO_TRIGGER_POLARITY_LOW,
541  FLEXIO_TRIGGER_SOURCE_INTERNAL,
542  userConfigPtr->sckPin, /* use SCK pin as input pin */
543  clockPolarity,
544  FLEXIO_PIN_CONFIG_DISABLED,
545  FLEXIO_TIMER_MODE_DISABLED);
546 }
547 
548 
549 /*FUNCTION**********************************************************************
550  *
551  * Function Name : FLEXIO_SPI_DRV_ReadData
552  * Description : reads data received by the module
553  *
554  *END**************************************************************************/
555 static void FLEXIO_SPI_DRV_ReadData(flexio_spi_master_state_t *master)
556 {
557  const FLEXIO_Type *baseAddr;
558  uint32_t data;
559  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
560 
561  baseAddr = g_flexioBase[master->flexioCommon.instance];
562  resourceIndex = master->flexioCommon.resourceIndex;
563 
564  /* Read data from shifter buffer */
565  if (master->bitOrder == FLEXIO_SPI_TRANSFER_LSB_FIRST)
566  {
567  /* For data size < 4 bytes our data is in the upper part of the buffer and must be shifted */
568  data = FLEXIO_ReadShifterBuffer(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_RW_MODE_NORMAL);
569  data >>= (32U - (8U * (uint32_t)(master->transferSize)));
570  }
571  else
572  {
573  data = FLEXIO_ReadShifterBuffer(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
574  }
575 
576  if ((master->rxRemainingBytes > 0U) && (master->rxData != NULL))
577  {
578  switch (master->transferSize)
579  {
581  *(uint8_t *)master->rxData = (uint8_t)data;
582  break;
584  *(uint16_t *)master->rxData = (uint16_t)data;
585  break;
587  *(uint32_t *)master->rxData = (uint32_t)data;
588  break;
589  default:
590  /* Not possible */
591  break;
592  }
593  /* Update rx buffer pointer and remaining bytes count */
594  master->rxData = &master->rxData[(master->transferSize)];
595  master->rxRemainingBytes -= (uint32_t)(master->transferSize);
596  }
597  else
598  {
599  /* No data to receive, just ignore the read data */
600  }
601 }
602 
603 
604 /*FUNCTION**********************************************************************
605  *
606  * Function Name : FLEXIO_SPI_DRV_WriteData
607  * Description : writes data to be transmitted by the module
608  *
609  *END**************************************************************************/
610 static void FLEXIO_SPI_DRV_WriteData(flexio_spi_master_state_t *master)
611 {
612  FLEXIO_Type *baseAddr;
613  uint32_t data = FLEXIO_SPI_DUMMYDATA;
614  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
615 
616  baseAddr = g_flexioBase[master->flexioCommon.instance];
617  resourceIndex = master->flexioCommon.resourceIndex;
618 
619  if (master->txRemainingBytes == 0U)
620  {
621  /* Done transmitting */
622  return;
623  }
624 
625  if ((master->txRemainingBytes > 0U) && (master->txData != NULL))
626  {
627  /* Read data from user buffer */
628  switch (master->transferSize)
629  {
631  data = (uint32_t)(*(const uint8_t *)master->txData);
632  break;
634  data = (uint32_t)(*(const uint16_t *)master->txData);
635  break;
637  data = (uint32_t)(*(const uint32_t *)master->txData);
638  break;
639  default:
640  /* Not possible */
641  break;
642  }
643  /* Update tx buffer pointer and remaining bytes count */
644  master->txData = &master->txData[master->transferSize];
645  master->txRemainingBytes -= (uint32_t)(master->transferSize);
646  /* Write data to shifter buffer */
647  if (master->bitOrder == FLEXIO_SPI_TRANSFER_LSB_FIRST)
648  {
649  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), data, FLEXIO_SHIFTER_RW_MODE_NORMAL);
650  }
651  else
652  {
653  /* Shift data before bit-swapping it to get the relevant bits in the lower part of the shifter */
654  data <<= 32U - (8U * (uint32_t)(master->transferSize));
655  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), data, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
656  }
657  }
658  else
659  {
660  /* Nothing to send, write dummy data in buffer */
661  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SPI_DUMMYDATA, FLEXIO_SHIFTER_RW_MODE_NORMAL);
662  }
663 }
664 
665 
666 
667 /*FUNCTION**********************************************************************
668  *
669  * Function Name : FLEXIO_SPI_DRV_MasterCheckStatus
670  * Description : Check status of SPI master transfer. This function can be
671  * called either in an interrupt routine or directly in polling
672  * mode to advance the SPI transfer.
673  *
674  *END**************************************************************************/
675 static void FLEXIO_SPI_DRV_MasterCheckStatus(void *stateStruct)
676 {
678  FLEXIO_Type *baseAddr;
679  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
680 
681  DEV_ASSERT(stateStruct != NULL);
682 
683  master = (flexio_spi_master_state_t *)stateStruct;
684  baseAddr = g_flexioBase[master->flexioCommon.instance];
685  resourceIndex = master->flexioCommon.resourceIndex;
686 
687  /* Check for errors */
688  if (FLEXIO_GetShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex)))
689  {
690  master->status = STATUS_SPI_TX_UNDERRUN;
691  /* Force the transfer to stop */
692  FLEXIO_SPI_DRV_MasterStopTransfer(master);
693  /* Call callback to announce the event to the user */
694  if (master->callback != NULL)
695  {
696  master->callback(master, SPI_EVENT_END_TRANSFER, master->callbackParam);
697  }
698  return;
699  }
700  if (FLEXIO_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
701  {
702  master->status = STATUS_SPI_RX_OVERRUN;
703  /* Force the transfer to stop */
704  FLEXIO_SPI_DRV_MasterStopTransfer(master);
705  /* Call callback to announce the event to the user */
706  if (master->callback != NULL)
707  {
708  master->callback(master, SPI_EVENT_END_TRANSFER, master->callbackParam);
709  }
710  return;
711  }
712  /* Check if data was received */
713  if (FLEXIO_GetShifterStatus(baseAddr, RX_SHIFTER(resourceIndex)))
714  {
715  FLEXIO_SPI_DRV_ReadData(master);
716  }
717  /* Check if transmitter needs more data */
718  if (FLEXIO_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)))
719  {
720  FLEXIO_SPI_DRV_WriteData(master);
721  if (master->txRemainingBytes == 0U)
722  {
723  /* No more data to transmit, disable tx interrupts */
724  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
725  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
726  }
727  }
728 
729  /* Check there is any data left */
730  if ((master->txRemainingBytes == 0U) && (master->rxRemainingBytes == 0U))
731  {
732  /* Record success if there was no error */
733  if (master->status == STATUS_BUSY)
734  {
735  master->status = STATUS_SUCCESS;
736  }
737  /* End transfer */
738  FLEXIO_SPI_DRV_MasterStopTransfer(master);
739  /* Call callback to announce the event to the user */
740  if (master->callback != NULL)
741  {
742  master->callback(master, SPI_EVENT_END_TRANSFER, master->callbackParam);
743  }
744  }
745 }
746 
747 
748 /*FUNCTION**********************************************************************
749  *
750  * Function Name : FLEXIO_SPI_DRV_MasterComputeTxRegAddr
751  * Description : Computes the address of the register used for DMA tx transfer
752  *
753  *END**************************************************************************/
754 static uint32_t FLEXIO_SPI_DRV_MasterComputeTxRegAddr(const flexio_spi_master_state_t *master)
755 {
756  uint32_t addr;
757  const FLEXIO_Type *baseAddr;
758  uint8_t shifter;
759 
760  baseAddr = g_flexioBase[master->flexioCommon.instance];
761  shifter = TX_SHIFTER(master->flexioCommon.resourceIndex);
762  if (master->bitOrder == FLEXIO_SPI_TRANSFER_LSB_FIRST)
763  {
764  addr = (uint32_t)(&(baseAddr->SHIFTBUF[shifter]));
765  }
766  else
767  {
768  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter])) + (sizeof(uint32_t) - (uint32_t)master->transferSize);
769  }
770  return addr;
771 }
772 
773 
774 /*FUNCTION**********************************************************************
775  *
776  * Function Name : FLEXIO_SPI_DRV_MasterComputeRxRegAddr
777  * Description : Computes the address of the register used for DMA rx transfer
778  *
779  *END**************************************************************************/
780 static uint32_t FLEXIO_SPI_DRV_MasterComputeRxRegAddr(const flexio_spi_master_state_t *master)
781 {
782  uint32_t addr;
783  const FLEXIO_Type *baseAddr;
784  uint8_t shifter;
785 
786  baseAddr = g_flexioBase[master->flexioCommon.instance];
787  shifter = RX_SHIFTER(master->flexioCommon.resourceIndex);
788  if (master->bitOrder == FLEXIO_SPI_TRANSFER_LSB_FIRST)
789  {
790  addr = (uint32_t)(&(baseAddr->SHIFTBUF[shifter])) + (sizeof(uint32_t) - (uint32_t)master->transferSize);
791  }
792  else
793  {
794  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter]));
795  }
796  return addr;
797 }
798 
799 
800 /*FUNCTION**********************************************************************
801  *
802  * Function Name : FLEXIO_SPI_DRV_MasterStartDmaTransfer
803  * Description : Starts a DMA transfer
804  *
805  *END**************************************************************************/
806 static void FLEXIO_SPI_DRV_MasterStartDmaTransfer(flexio_spi_master_state_t *master)
807 {
808  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
809  FLEXIO_Type *baseAddr;
810  uint32_t addr;
811  /* Table to map flexio_spi transfer sizes to EDMA transfer sizes */
812  static const edma_transfer_size_t dmaTransferSize[FLEXIO_SPI_TRANSFER_4BYTE] =
814 
815 
816  baseAddr = g_flexioBase[master->flexioCommon.instance];
817  resourceIndex = master->flexioCommon.resourceIndex;
818 
819  if (master->txData != NULL)
820  {
821  addr = (uint32_t)(master->txData);
822  }
823  else
824  {
825  /* if there is no data to transmit, use dummy data as source for DMA transfer */
826  master->dummyDmaData = FLEXIO_SPI_DUMMYDATA;
827  addr = (uint32_t)(&(master->dummyDmaData));
828  }
829 
830  /* Configure the transfer control descriptor for the Tx channel */
831  (void)EDMA_DRV_ConfigMultiBlockTransfer(master->txDMAChannel,
833  addr,
834  FLEXIO_SPI_DRV_MasterComputeTxRegAddr(master),
835  dmaTransferSize[(uint32_t)master->transferSize - 1U],
836  (uint32_t)master->transferSize,
837  master->txRemainingBytes / (uint32_t)master->transferSize,
838  true);
839  if (master->txData == NULL)
840  {
841  /* if there is no data to transmit, don't increment source offset */
842  EDMA_DRV_SetSrcOffset(master->txDMAChannel, 0);
843  }
844 
845  if (master->rxData != NULL)
846  {
847  addr = (uint32_t)(master->rxData);
848  }
849  else
850  {
851  /* if there is no data to receive, use dummy data as destination for DMA transfer */
852  addr = (uint32_t)(&(master->dummyDmaData));
853  }
854 
855  /* Configure the transfer control descriptor for the Rx channel */
856  (void)EDMA_DRV_ConfigMultiBlockTransfer(master->rxDMAChannel,
858  FLEXIO_SPI_DRV_MasterComputeRxRegAddr(master),
859  addr,
860  dmaTransferSize[(uint32_t)master->transferSize - 1U],
861  (uint32_t)master->transferSize,
862  master->rxRemainingBytes / (uint32_t)master->transferSize,
863  true);
864  if (master->rxData == NULL)
865  {
866  /* if there is no data to receive, don't increment destination offset */
867  EDMA_DRV_SetDestOffset(master->rxDMAChannel, 0);
868  }
869  /* Setup callback for DMA transfer end */
870  (void)EDMA_DRV_InstallCallback(master->rxDMAChannel,
871  (edma_callback_t)(FLEXIO_SPI_DRV_MasterEndDmaTransfer),
872  (void*)(master));
873 
874  /* Start both DMA channels */
875  (void)EDMA_DRV_StartChannel(master->txDMAChannel);
876  (void)EDMA_DRV_StartChannel(master->rxDMAChannel);
877 
878  /* Enable FlexIO DMA requests for both shifters */
879  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))), true);
880 }
881 
882 
885 /*******************************************************************************
886  * Code
887  ******************************************************************************/
888 
889 /*FUNCTION**********************************************************************
890  *
891  * Function Name : FLEXIO_SPI_DRV_MasterInit
892  * Description : Initialize the FLEXIO_SPI master mode driver
893  *
894  * Implements : FLEXIO_SPI_DRV_MasterInit_Activity
895  *END**************************************************************************/
897  const flexio_spi_master_user_config_t * userConfigPtr,
898  flexio_spi_master_state_t * master)
899 {
900  status_t retCode;
901  uint32_t inputClock;
902  status_t clkErr;
903  status_t osifError = STATUS_SUCCESS;
904  uint8_t dmaReqTx;
905  uint8_t dmaReqRx;
906 
907  DEV_ASSERT(master != NULL);
908  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
909  /* Check that device was initialized */
910  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
911  DEV_ASSERT((userConfigPtr->transferSize == FLEXIO_SPI_TRANSFER_1BYTE) ||
912  (userConfigPtr->transferSize == FLEXIO_SPI_TRANSFER_2BYTE) ||
913  (userConfigPtr->transferSize == FLEXIO_SPI_TRANSFER_4BYTE));
914 
915  /* Get the protocol clock frequency */
916  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[instance], &inputClock);
917  DEV_ASSERT(clkErr == STATUS_SUCCESS);
918  DEV_ASSERT(inputClock > 0U);
919 
920  /* Instruct the resource allocator that we need two shifters/timers */
921  master->flexioCommon.resourceCount = 2U;
922  /* Common FlexIO driver initialization */
923  retCode = FLEXIO_DRV_InitDriver(instance, &(master->flexioCommon));
924  if (retCode != STATUS_SUCCESS)
925  { /* Initialization failed, not enough resources */
926  return retCode;
927  }
928  /* Initialize the semaphore */
929  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
930  {
931  osifError = OSIF_SemaCreate(&(master->idleSemaphore), 0U);
932  DEV_ASSERT(osifError == STATUS_SUCCESS);
933  }
934 
935  /* Initialize driver-specific context structure */
936  master->driverType = userConfigPtr->driverType;
937  master->bitOrder = userConfigPtr->bitOrder;
938  master->transferSize = userConfigPtr->transferSize;
939  master->callback = userConfigPtr->callback;
940  master->callbackParam = userConfigPtr->callbackParam;
941  master->blocking = false;
942  master->driverIdle = true;
943  master->master = true;
944  master->status = STATUS_SUCCESS;
945 
946  /* Configure device for SPI mode */
947  FLEXIO_SPI_DRV_MasterConfigure(master, userConfigPtr, inputClock);
948 
949  /* Set up transfer engine */
950  switch (userConfigPtr->driverType)
951  {
953  master->flexioCommon.isr = FLEXIO_SPI_DRV_MasterCheckStatus;
954  break;
956  /* Nothing to do here, FLEXIO_SPI_DRV_MasterGetStatus() will handle the transfer */
957  break;
959  /* Store DMA channel numbers */
960  master->rxDMAChannel = userConfigPtr->rxDMAChannel;
961  master->txDMAChannel = userConfigPtr->txDMAChannel;
962  /* Configure DMA request sources */
963  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(master->flexioCommon.resourceIndex)];
964  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(master->flexioCommon.resourceIndex)];
965  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
966  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
967  break;
968  default:
969  /* Impossible type - do nothing */
970  break;
971  }
972 
973  (void)clkErr;
974  (void)osifError;
975  return STATUS_SUCCESS;
976 }
977 
978 /*FUNCTION**********************************************************************
979  *
980  * Function Name : FLEXIO_SPI_DRV_MasterDeinit
981  * Description : De-initialize the FLEXIO_SPI master mode driver
982  *
983  * Implements : FLEXIO_SPI_DRV_MasterDeinit_Activity
984  *END**************************************************************************/
986 {
987  DEV_ASSERT(master != NULL);
988 
989  /* Check if driver is busy */
990  DEV_ASSERT(master->driverIdle);
991 
992  /* Destroy the semaphore */
993  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
994  {
995  (void)OSIF_SemaDestroy(&(master->idleSemaphore));
996  }
997 
998  return FLEXIO_DRV_DeinitDriver(&(master->flexioCommon));
999 }
1000 
1001 
1002 /*FUNCTION**********************************************************************
1003  *
1004  * Function Name : FLEXIO_SPI_DRV_MasterSetBaudRate
1005  * Description : Set the baud rate for any subsequent SPI communication
1006  *
1007  * Implements : FLEXIO_SPI_DRV_MasterSetBaudRate_Activity
1008  *END**************************************************************************/
1010 {
1011  FLEXIO_Type *baseAddr;
1012  uint16_t divider;
1013  uint16_t timerCmp;
1014  uint32_t inputClock;
1015  status_t clkErr;
1016  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1017 
1018  DEV_ASSERT(master != NULL);
1019 
1020  baseAddr = g_flexioBase[master->flexioCommon.instance];
1021  resourceIndex = master->flexioCommon.resourceIndex;
1022 
1023  /* Check if driver is busy */
1024  DEV_ASSERT(master->driverIdle);
1025  /* Get the protocol clock frequency */
1026  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1027  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1028  DEV_ASSERT(inputClock > 0U);
1029 
1030  /* Compute divider */
1031  FLEXIO_SPI_DRV_MasterComputeBaudRateDivider(baudRate, &divider, inputClock);
1032 
1033  /* Configure timer divider in the lower 8 bits of TIMCMP[CMP] */
1034  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCK_TIMER(resourceIndex));
1035  timerCmp = (uint16_t)((timerCmp & 0xFF00U) | divider);
1036  FLEXIO_SetTimerCompare(baseAddr, SCK_TIMER(resourceIndex), timerCmp);
1037 
1038  (void)clkErr;
1039  return STATUS_SUCCESS;
1040 }
1041 
1042 
1043 
1044 /*FUNCTION**********************************************************************
1045  *
1046  * Function Name : FLEXIO_SPI_DRV_MasterGetBaudRate
1047  * Description : Get the currently configured baud rate
1048  *
1049  * Implements : FLEXIO_SPI_DRV_MasterGetBaudRate_Activity
1050  *END**************************************************************************/
1052 {
1053  const FLEXIO_Type *baseAddr;
1054  uint16_t divider;
1055  uint16_t timerCmp;
1056  uint32_t inputClock;
1057  status_t clkErr;
1058  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1059 
1060  DEV_ASSERT(master != NULL);
1061  DEV_ASSERT(baudRate != NULL);
1062 
1063  baseAddr = g_flexioBase[master->flexioCommon.instance];
1064  resourceIndex = master->flexioCommon.resourceIndex;
1065 
1066  /* Get the protocol clock frequency */
1067  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1068  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1069  DEV_ASSERT(inputClock > 0U);
1070 
1071  /* Get the currently configured divider */
1072  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCK_TIMER(resourceIndex));
1073  divider = (uint16_t)(timerCmp & 0x00FFU);
1074 
1075  /* Compute baud rate: input_clock / (2 * (divider + 1)). Round to nearest integer */
1076  *baudRate = (inputClock + divider + 1U) / (2U * ((uint32_t)divider + 1U));
1077 
1078  (void)clkErr;
1079  return STATUS_SUCCESS;
1080 }
1081 
1082 
1083 
1084 
1085 /*FUNCTION**********************************************************************
1086  *
1087  * Function Name : FLEXIO_SPI_DRV_MasterTransfer
1088  * Description : Perform an SPI master non-blocking transaction
1089  *
1090  * Implements : FLEXIO_SPI_DRV_MasterTransfer_Activity
1091  *END**************************************************************************/
1093  const uint8_t *txData,
1094  uint8_t *rxData,
1095  uint32_t dataSize)
1096 {
1097  FLEXIO_Type *baseAddr;
1098  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1099 
1100  DEV_ASSERT(master != NULL);
1101  DEV_ASSERT((dataSize % (uint32_t)(master->transferSize)) == 0U);
1102  DEV_ASSERT((txData != NULL) || (rxData != NULL));
1103 
1104  baseAddr = g_flexioBase[master->flexioCommon.instance];
1105  resourceIndex = master->flexioCommon.resourceIndex;
1106 
1107  /* Check if driver is busy */
1108  DEV_ASSERT(master->driverIdle);
1109  /* Initialize transfer data */
1110  master->txData = txData;
1111  master->rxData = rxData;
1112  master->txRemainingBytes = dataSize;
1113  master->rxRemainingBytes = dataSize;
1114  master->driverIdle = false;
1115  master->status = STATUS_BUSY;
1116 
1117  /* Enable timers and shifters */
1118  FLEXIO_SPI_DRV_MasterEnableTransfer(master);
1119  /* Enable transfer engine */
1120  switch (master->driverType)
1121  {
1123  /* Enable interrupts for Rx and Tx shifters */
1124  FLEXIO_SetShifterInterrupt(baseAddr,
1125  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
1126  true);
1127  FLEXIO_SetShifterErrorInterrupt(baseAddr,
1128  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
1129  true);
1130  break;
1132  /* Call FLEXIO_SPI_DRV_MasterCheckStatus once to send the first byte */
1133  FLEXIO_SPI_DRV_MasterCheckStatus(master);
1134  break;
1136  FLEXIO_SPI_DRV_MasterStartDmaTransfer(master);
1137  break;
1138  default:
1139  /* Impossible type - do nothing */
1140  break;
1141  }
1142 
1143  return STATUS_SUCCESS;
1144 }
1145 
1146 
1147 /*FUNCTION**********************************************************************
1148  *
1149  * Function Name : FLEXIO_SPI_DRV_MasterTransferBlocking
1150  * Description : Perform an SPI master blocking transaction
1151  *
1152  * Implements : FLEXIO_SPI_DRV_MasterTransferBlocking_Activity
1153  *END**************************************************************************/
1155  const uint8_t *txData,
1156  uint8_t *rxData,
1157  uint32_t dataSize,
1158  uint32_t timeout)
1159 {
1160  status_t status;
1161 
1162  /* mark transfer as blocking */
1163  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1164  {
1165  master->blocking = true;
1166  }
1167  status = FLEXIO_SPI_DRV_MasterTransfer(master, txData, rxData, dataSize);
1168  if (status != STATUS_SUCCESS)
1169  {
1170  /* Transfer could not be started */
1171  master->blocking = false;
1172  return status;
1173  }
1174 
1175  /* Wait for transfer to end */
1176  return FLEXIO_SPI_DRV_MasterWaitTransferEnd(master, timeout);
1177 }
1178 
1179 
1180 /*FUNCTION**********************************************************************
1181  *
1182  * Function Name : FLEXIO_SPI_DRV_MasterTransferAbort
1183  * Description : Aborts a non-blocking SPI master transaction
1184  *
1185  * Implements : FLEXIO_SPI_DRV_MasterTransferAbort_Activity
1186  *END**************************************************************************/
1188 {
1189  DEV_ASSERT(master != NULL);
1190 
1191  /* Check if driver is busy */
1192  if (master->driverIdle)
1193  {
1194  return STATUS_SUCCESS;
1195  }
1196 
1197  master->status = STATUS_SPI_ABORTED;
1198  FLEXIO_SPI_DRV_MasterStopTransfer(master);
1199 
1200  return STATUS_SUCCESS;
1201 }
1202 
1203 
1204 /*FUNCTION**********************************************************************
1205  *
1206  * Function Name : FLEXIO_SPI_DRV_MasterGetStatus
1207  * Description : Get the status of the current non-blocking SPI master transaction
1208  *
1209  * Implements : FLEXIO_SPI_DRV_MasterGetStatus_Activity
1210  *END**************************************************************************/
1212 {
1213  uint32_t remainingBytes;
1214 
1215  DEV_ASSERT(master != NULL);
1216 
1217  /* Initialize with the actual remaining bytes count */
1218  remainingBytes = master->rxRemainingBytes;
1219 
1220  if (!master->driverIdle)
1221  {
1222  switch(master->driverType)
1223  {
1225  /* In polling mode advance the SPI transfer here */
1226  FLEXIO_SPI_DRV_MasterCheckStatus(master);
1227  break;
1228 
1230  /* In DMA mode just update the remaining count.
1231  DO NOT write master->txRemainingBytes directly !!! */
1232  remainingBytes = EDMA_DRV_GetRemainingMajorIterationsCount(master->rxDMAChannel);
1233  break;
1234 
1235  default:
1236  /* Nothing */
1237  break;
1238  }
1239 
1240  }
1241 
1242  if (bytesRemaining != NULL)
1243  {
1244  *bytesRemaining = remainingBytes;
1245  }
1246 
1247  return master->status;
1248 }
1249 
1250 
1251 
1252 /*FUNCTION**********************************************************************
1253  *
1254  * Function Name : FLEXIO_SPI_DRV_SlaveInit
1255  * Description : Initialize the FLEXIO_SPI slave mode driver
1256  *
1257  * Implements : FLEXIO_SPI_DRV_SlaveInit_Activity
1258  *END**************************************************************************/
1260  const flexio_spi_slave_user_config_t * userConfigPtr,
1261  flexio_spi_slave_state_t * slave)
1262 {
1263  status_t retCode;
1264  status_t osifError = STATUS_SUCCESS;
1265  uint8_t dmaReqTx;
1266  uint8_t dmaReqRx;
1267 
1268  DEV_ASSERT(slave != NULL);
1269  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
1270  /* Check that device was initialized */
1271  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
1272 
1273  /* Instruct the resource allocator that we need two shifters/timers */
1274  slave->flexioCommon.resourceCount = 2U;
1275  /* Common FlexIO driver initialization */
1276  retCode = FLEXIO_DRV_InitDriver(instance, &(slave->flexioCommon));
1277  if (retCode != STATUS_SUCCESS)
1278  { /* Initialization failed, not enough resources */
1279  return retCode;
1280  }
1281  /* Initialize the semaphore */
1282  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1283  {
1284  osifError = OSIF_SemaCreate(&(slave->idleSemaphore), 0U);
1285  DEV_ASSERT(osifError == STATUS_SUCCESS);
1286  }
1287 
1288  /* Initialize driver context structure */
1289  slave->driverType = userConfigPtr->driverType;
1290  slave->bitOrder = userConfigPtr->bitOrder;
1291  slave->transferSize = userConfigPtr->transferSize;
1292  slave->callback = userConfigPtr->callback;
1293  slave->callbackParam = userConfigPtr->callbackParam;
1294  slave->blocking = false;
1295  slave->driverIdle = true;
1296  slave->master = false;
1297  slave->status = STATUS_SUCCESS;
1298 
1299  /* Configure device for SPI mode */
1300  FLEXIO_SPI_DRV_SlaveConfigure(slave, userConfigPtr);
1301 
1302  /* Set up transfer engine */
1303  switch (userConfigPtr->driverType)
1304  {
1306  slave->flexioCommon.isr = FLEXIO_SPI_DRV_MasterCheckStatus;
1307  break;
1309  /* Nothing to do here, FLEXIO_SPI_DRV_MasterGetStatus() will handle the transfer */
1310  break;
1312  /* Store DMA channel numbers */
1313  slave->rxDMAChannel = userConfigPtr->rxDMAChannel;
1314  slave->txDMAChannel = userConfigPtr->txDMAChannel;
1315  /* Configure DMA request sources */
1316  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(slave->flexioCommon.resourceIndex)];
1317  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(slave->flexioCommon.resourceIndex)];
1318  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
1319  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
1320  break;
1321  default:
1322  /* Impossible type - do nothing */
1323  break;
1324  }
1325 
1326  (void)osifError;
1327  return STATUS_SUCCESS;
1328 }
1329 
1330 
1331 
1332 /*******************************************************************************
1333  * EOF
1334  ******************************************************************************/
status_t FLEXIO_SPI_DRV_MasterGetBaudRate(flexio_spi_master_state_t *master, uint32_t *baudRate)
Get the currently configured baud rate.
uint32_t EDMA_DRV_GetRemainingMajorIterationsCount(uint8_t virtualChannel)
Returns the remaining major loop iteration count.
Definition: edma_driver.c:1346
status_t EDMA_DRV_InstallCallback(uint8_t virtualChannel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:336
flexio_spi_transfer_size_t transferSize
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
status_t FLEXIO_SPI_DRV_MasterTransferBlocking(flexio_spi_master_state_t *master, const uint8_t *txData, uint8_t *rxData, uint32_t dataSize, uint32_t timeout)
Perform a blocking SPI master transaction.
status_t EDMA_DRV_ConfigMultiBlockTransfer(uint8_t virtualChannel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t blockSize, uint32_t blockCount, bool disableReqOnCompletion)
Configures a multiple block data transfer with DMA.
Definition: edma_driver.c:662
status_t FLEXIO_SPI_DRV_MasterTransfer(flexio_spi_master_state_t *master, const uint8_t *txData, uint8_t *rxData, uint32_t dataSize)
Perform a non-blocking SPI master transaction.
#define FLEXIO_INSTANCE_COUNT
Definition: S32K118.h:3350
flexio_spi_transfer_bit_order_t bitOrder
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
void EDMA_DRV_SetDestOffset(uint8_t virtualChannel, int16_t offset)
Configures the destination address signed offset for the eDMA channel.
Definition: edma_driver.c:1226
status_t EDMA_DRV_StopChannel(uint8_t virtualChannel)
Stops the eDMA channel.
Definition: edma_driver.c:952
#define DEV_ASSERT(x)
Definition: devassert.h:77
status_t FLEXIO_SPI_DRV_MasterGetStatus(flexio_spi_master_state_t *master, uint32_t *bytesRemaining)
Get the status of the current non-blocking SPI master transaction.
Slave configuration structure.
flexio_driver_type_t driverType
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:255
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_driver.h:200
volatile uint32_t SHIFTBUFBIS[4u]
Definition: S32K118.h:3336
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
const clock_names_t g_flexioClock[(1u)]
Definition: flexio_common.c:65
flexio_spi_transfer_size_t transferSize
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
FLEXIO_Type *const g_flexioBase[(1u)]
Definition: flexio_common.c:56
Master configuration structure.
status_t FLEXIO_SPI_DRV_MasterSetBaudRate(flexio_spi_master_state_t *master, uint32_t baudRate)
Set the baud rate for any subsequent SPI communication.
void EDMA_DRV_SetSrcOffset(uint8_t virtualChannel, int16_t offset)
Configures the source address signed offset for the eDMA channel.
Definition: edma_driver.c:1076
volatile uint32_t SHIFTBUF[4u]
Definition: S32K118.h:3334
status_t FLEXIO_SPI_DRV_SlaveInit(uint32_t instance, const flexio_spi_slave_user_config_t *userConfigPtr, flexio_spi_slave_state_t *slave)
Initialize the FLEXIO_SPI slave mode driver.
const uint8_t g_flexioDMASrc[(1u)][(4U)]
Definition: flexio_common.c:68
flexio_spi_transfer_bit_order_t bitOrder
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
flexio_device_state_t * g_flexioDeviceStatePtr[(1u)]
Definition: flexio_common.c:59
status_t FLEXIO_SPI_DRV_MasterInit(uint32_t instance, const flexio_spi_master_user_config_t *userConfigPtr, flexio_spi_master_state_t *master)
Initialize the FLEXIO_SPI master mode driver.
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
status_t EDMA_DRV_StartChannel(uint8_t virtualChannel)
Starts an eDMA channel.
Definition: edma_driver.c:921
status_t FLEXIO_SPI_DRV_MasterDeinit(flexio_spi_master_state_t *master)
De-initialize the FLEXIO_SPI master mode driver.
status_t EDMA_DRV_SetChannelRequest(uint8_t virtualChannel, uint8_t req)
Configures the DMA request for the eDMA channel.
Definition: edma_driver.c:983
status_t FLEXIO_SPI_DRV_MasterTransferAbort(flexio_spi_master_state_t *master)
Aborts a non-blocking SPI master transaction.
Master internal context structure.
void(* edma_callback_t)(void *parameter, edma_chn_status_t status)
Definition for the eDMA channel callback function.
Definition: edma_driver.h:266