lpspi_master_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-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 
87 #include <string.h>
88 #include "lpspi_master_driver.h"
89 #include "clock_manager.h"
90 #include "interrupt_manager.h"
91 #include "device_registers.h"
92 #include "lpspi_hw_access.h"
93 
94 
95 /*******************************************************************************
96  * Definitions
97  ******************************************************************************/
98 #define MICROSECONDS 1000000
99 /*******************************************************************************
100  * Variables
101  ******************************************************************************/
102 
103 /*******************************************************************************
104  * Prototypes
105  ******************************************************************************/
106 /* This function initialize a new SPI transfer */
107 static status_t LPSPI_DRV_MasterStartTransfer(uint32_t instance,
108  const uint8_t * sendBuffer,
109  uint8_t * receiveBuffer,
110  uint16_t transferByteCount);
111 
112 /* This function cleans up state structure and hardware after a transfer is complete .*/
113 static void LPSPI_DRV_MasterCompleteTransfer(uint32_t instance);
114 
115 /* Callback for DMA transfer done.*/
116 static void LPSPI_DRV_MasterCompleteDMATransfer(void* parameter, edma_chn_status_t status);
117 
119 static void LPSPI_DRV_MasterClearCountinuous(void* parameter, edma_chn_status_t status);
120 
121 /*******************************************************************************
122  * Code
123  ******************************************************************************/
124 
125 /*FUNCTION**********************************************************************
126  *
127  * Function Name : LPSPI_DRV_MasterInit
128  * Description : Initializes a LPSPI instance for interrupt driven master mode operation.
129  *
130  * This function uses an interrupt-driven method for transferring data.
131  * In this function, the term "spiConfig" is used to indicate the SPI device for which the LPSPI
132  * master is communicating.
133  * This function initializes the run-time state structure to track the ongoing
134  * transfers, un-gates the clock to the LPSPI module, resets the LPSPI module,
135  * configures the IRQ state structure, enables the module-level interrupt to the core, and
136  * enables the LPSPI module.
137  * Implements : LPSPI_DRV_MasterInit_Activity
138  *
139  *END**************************************************************************/
140 status_t LPSPI_DRV_MasterInit(uint32_t instance, lpspi_state_t * lpspiState,
141  const lpspi_master_config_t * spiConfig)
142 {
143  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
144  DEV_ASSERT(lpspiState != NULL);
145  DEV_ASSERT(spiConfig != NULL);
146  DEV_ASSERT(!((spiConfig->bitcount > 32U) && (spiConfig->lsbFirst == false)));
147  LPSPI_Type *base = g_lpspiBase[instance];
148  status_t errorCode = STATUS_SUCCESS;
149 
150  /* Save runtime structure pointers so irq handler can point to the correct state structure */
151  g_lpspiStatePtr[instance] = lpspiState;
152  /* Reset the LPSPI registers to their default state */
153  LPSPI_Init(base);
154  /* Set for master mode */
155  (void)LPSPI_SetMasterSlaveMode(base, LPSPI_MASTER);
156  /* Set Pin configuration such that SDO=out and SDI=in */
157  (void)LPSPI_SetPinConfigMode(base, LPSPI_SDI_IN_SDO_OUT, LPSPI_DATA_OUT_RETAINED, true);
158  /* Calculate the FIFO size for the LPSPI */
159  LPSPI_GetFifoSizes(base, &(lpspiState->fifoSize), NULL);
160 
161  /* Configure bus for this device. If NULL is passed, we assume the caller has
162  * preconfigured the bus and doesn't wish to re-configure it again for this transfer.
163  * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate
164  * then they can call this function separately.
165  */
166  errorCode = LPSPI_DRV_MasterConfigureBus(instance, spiConfig, NULL);
167  if (errorCode != STATUS_SUCCESS)
168  {
169  return errorCode;
170  }
171  /* When TX is null the value sent on the bus will be 0 */
172  lpspiState->dummy = 0;
173  /* Initialize the semaphore */
174  errorCode = OSIF_SemaCreate(&(lpspiState->lpspiSemaphore), 0);
175  DEV_ASSERT(errorCode == STATUS_SUCCESS);
176  /* Enable the interrupt */
177  INT_SYS_EnableIRQ(g_lpspiIrqId[instance]);
178  /* Finally, enable LPSPI */
179  LPSPI_Enable(base);
180  return errorCode;
181 }
182 
183 /*FUNCTION**********************************************************************
184  *
185  * Function Name : LPSPI_DRV_MasterDeinit
186  * Description : Shuts down a LPSPI instance.
187  *
188  * This function resets the LPSPI peripheral, gates its clock, and disables the interrupt to
189  * the core. It first checks to see if a transfer is in progress and if so returns an error
190  * status.
191  * Implements : LPSPI_DRV_MasterDeinit_Activity
192  *
193  *END**************************************************************************/
195 {
196  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
197  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
198  /* Instantiate local variable of type lpspi_state_t and point to global state */
199  const lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
200  LPSPI_Type *base = g_lpspiBase[instance];
201  status_t errorCode = STATUS_SUCCESS;
202 
203  /* Check if a transfer is still in progress */
204  DEV_ASSERT(lpspiState->isTransferInProgress == false);
205 
206  /* Reset the LPSPI registers to their default state, inlcuding disabling the LPSPI */
207  LPSPI_Init(base);
208  /* Disable the interrupt */
209  INT_SYS_DisableIRQ(g_lpspiIrqId[instance]);
210  /* Clear the state pointer. */
211  g_lpspiStatePtr[instance] = NULL;
212 
213  /* Destroy the semaphore */
214  errorCode = OSIF_SemaDestroy(&(lpspiState->lpspiSemaphore));
215  DEV_ASSERT(errorCode == STATUS_SUCCESS);
216  return errorCode;
217 }
218 
219 /*FUNCTION**********************************************************************
220  *
221  * Function Name : LPSPI_DRV_MasterSetDelay
222  * Description : Configures the LPSPI master mode bus timing delay options.
223  *
224  * This function involves the LPSPI module's delay options to
225  * "fine tune" some of the signal timings and match the timing needs of a slower peripheral device.
226  * This is an optional function that can be called after the LPSPI module has been initialized for
227  * master mode. The timings are adjusted in terms of cycles of the baud rate clock.
228  * The bus timing delays that can be adjusted are listed below:
229  *
230  * SCK to PCS Delay: Adjustable delay option between the last edge of SCK to the de-assertion
231  * of the PCS signal.
232  *
233  * PCS to SCK Delay: Adjustable delay option between the assertion of the PCS signal to the
234  * first SCK edge.
235  *
236  * Delay between Transfers: Adjustable delay option between the de-assertion of the PCS signal for
237  * a frame to the assertion of the PCS signal for the next frame.
238  * Implements : LPSPI_DRV_MasterSetDelay_Activity
239  *
240  *END**************************************************************************/
241 status_t LPSPI_DRV_MasterSetDelay(uint32_t instance, uint32_t delayBetwenTransfers,
242  uint32_t delaySCKtoPCS, uint32_t delayPCStoSCK)
243 {
244  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
245  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
246  /* Instantiate local variable of type lpspi_state_t and point to global state */
247  const lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
248  LPSPI_Type *base = g_lpspiBase[instance];
249  status_t errorCode = STATUS_SUCCESS;
250  uint32_t realDelayBetwenTransfers, realDelaySCKtoPCS, realDelayPCStoSCK;
251  lpspi_prescaler_t prescaler;
252  /* Disable module */
253  errorCode = LPSPI_Disable(base);
254  if (errorCode != STATUS_SUCCESS)
255  {
256  return errorCode;
257  }
258  prescaler = LPSPI_GetClockPrescaler(base);
259  realDelayBetwenTransfers = delayBetwenTransfers * lpspiState->lpspiSrcClk / s_baudratePrescaler[prescaler] / (uint32_t)MICROSECONDS;
260  realDelaySCKtoPCS = delaySCKtoPCS * lpspiState->lpspiSrcClk / s_baudratePrescaler[prescaler] / (uint32_t)MICROSECONDS;
261  realDelayPCStoSCK = delayPCStoSCK * lpspiState->lpspiSrcClk/ s_baudratePrescaler[prescaler] / (uint32_t)MICROSECONDS;
262  /* Verify if current prescaler can be used for this configuration of delays
263  * If a delay is out of range, it will be adjusted to min or max value */
264  if (realDelayBetwenTransfers > (uint32_t)257U)
265  {
266  realDelayBetwenTransfers = (uint32_t)257U;
267  }
268  if(realDelaySCKtoPCS > (uint32_t)256U)
269  {
270  realDelaySCKtoPCS = (uint32_t)256U;
271  }
272  if(realDelayPCStoSCK > (uint32_t)256U)
273  {
274  realDelayPCStoSCK = (uint32_t)256U;
275  }
276  if (realDelayBetwenTransfers < (uint32_t)2U)
277  {
278  realDelayBetwenTransfers = (uint32_t)2U;
279  }
280  if(realDelaySCKtoPCS == (uint32_t)0)
281  {
282  realDelaySCKtoPCS = (uint32_t)1U;
283  }
284  if(realDelayPCStoSCK == (uint32_t)0U)
285  {
286  realDelayPCStoSCK = (uint32_t)1U;
287  }
288 
289  (void)LPSPI_SetDelay(base, LPSPI_SCK_TO_PCS, realDelaySCKtoPCS-1U);
290  (void)LPSPI_SetDelay(base, LPSPI_PCS_TO_SCK, realDelayPCStoSCK-1U);
291  (void)LPSPI_SetDelay(base, LPSPI_BETWEEN_TRANSFER, realDelayBetwenTransfers-2U);
292  /* Enable module */
293  LPSPI_Enable(base);
294  return errorCode;
295 }
296 
297 /*FUNCTION**********************************************************************
298  *
299  * Function Name : LPSPI_DRV_MasterConfigureBus
300  * Description : Configures the LPSPI port physical parameters to access a device on the bus when
301  * the LSPI instance is configured for interrupt operation.
302  *
303  * In this function, the term "spiConfig" is used to indicate the SPI device for which the LPSPI
304  * master is communicating. This is an optional function as the spiConfig parameters are
305  * normally configured in the initialization function or the transfer functions, where these various
306  * functions would call the configure bus function.
307  * The user can pass in a different spiConfig structure to the transfer function which contains
308  * the parameters for the SPI bus to allow for communication to a different SPI device
309  * (the transfer function then calls this function). However, the user also has the option to call
310  * this function directly especially to get the calculated baud rate, at which point they may pass
311  * in NULL for the spiConfig structure in the transfer function (assuming they have called this
312  * configure bus function first).
313  * Implements : LPSPI_DRV_MasterConfigureBus_Activity
314  *
315  *END**************************************************************************/
317  const lpspi_master_config_t * spiConfig,
318  uint32_t * calculatedBaudRate)
319 {
320  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
321  DEV_ASSERT(spiConfig != NULL);
322  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
323  /* Instantiate local variable of type lpspi_state_t and point to global state */
324  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
325  LPSPI_Type *base = g_lpspiBase[instance];
326  uint32_t baudRate;
327 
328  /* The Transmit Command Register (TCR) Prescale value is calculated as part of the baud rate
329  calculation. The value is stored in the run-time state structure for later programming
330  in the TCR. */
331  uint32_t tcrPrescaleValue;
332 
333  /* First, per the spec, we need to disable the LPSPI module before setting the delay */
334 
335  if (LPSPI_Disable(base) != STATUS_SUCCESS)
336  {
337  /* If error is returned, the LPSPI is busy */
338  return STATUS_ERROR;
339  }
340 
341  /* Check the bitcount to make sure it falls within the boundary conditions */
342  if ((spiConfig->bitcount < 8U) || (spiConfig->bitcount > 4096U))
343  {
344  return STATUS_ERROR;
345  }
346 
347  /* Configure internal state structure for LPSPI */
348  lpspiState->bitsPerFrame = spiConfig->bitcount;
349  lpspiState->lpspiSrcClk = spiConfig->lpspiSrcClk;
350  lpspiState->isPcsContinuous = spiConfig->isPcsContinuous;
351  lpspiState->lsb = spiConfig->lsbFirst;
352  /* Save transfer type DMA/Interrupt */
353  lpspiState->transferType = spiConfig->transferType;
354  /* Update transfer status */
355  lpspiState->isTransferInProgress = false;
356  lpspiState->isBlocking = false;
357  /* Calculate the bytes/frame for lpspiState->bytesPerFrame. */
358  lpspiState->bytesPerFrame = (uint16_t)((lpspiState->bitsPerFrame + 7U) / 8U);
359  /* Due to DMA limitations frames of 3 bytes/frame will be internally handled as 4 bytes/frame. */
360  if (lpspiState->bytesPerFrame == 3U)
361  {
362  lpspiState->bytesPerFrame = 4U;
363  }
364  /* Due to some limitations all frames bigger than 4 bytes/frame must be composed only from 4 bytes chunks. */
365  if (lpspiState->bytesPerFrame > 4U)
366  {
367  lpspiState->bytesPerFrame = (((lpspiState->bytesPerFrame - 1U) / 4U) + 1U) * 4U;
368  }
369  /* Store DMA channel number used in transfer */
370  lpspiState->rxDMAChannel = spiConfig->rxDMAChannel;
371  lpspiState->txDMAChannel = spiConfig->txDMAChannel;
372  /* Store callback */
373  lpspiState->callback = spiConfig->callback;
374  lpspiState->callbackParam = spiConfig->callbackParam;
375  /* Configure the desired PCS polarity */
376  (void)LPSPI_SetPcsPolarityMode(base, spiConfig->whichPcs, spiConfig->pcsPolarity);
377  /* Set up the baud rate */
378  baudRate = LPSPI_SetBaudRate(base, spiConfig->bitsPerSec, spiConfig->lpspiSrcClk,
379  &tcrPrescaleValue);
380  /* Enable sampling point delay */
381  LPSPI_SetSamplingPoint(base, true);
382  /* Now, re-enable the LPSPI module */
383  LPSPI_Enable(base);
384  /* If the baud rate return is "0", it means there was an error */
385  if (baudRate == (uint32_t)0)
386  {
387  return STATUS_ERROR;
388  }
389  /* If the user wishes to know the calculated baud rate, then pass it back */
390  if (calculatedBaudRate != NULL)
391  {
392  *calculatedBaudRate = baudRate;
393  }
394  /* Write the TCR for this transfer. */
395  lpspi_tx_cmd_config_t txCmdCfg =
396  {
397  .frameSize = lpspiState->bitsPerFrame,
398  .width = LPSPI_SINGLE_BIT_XFER,
399  .txMask = false,
400  .rxMask = false,
401  .contCmd = false,
402  .contTransfer = spiConfig->isPcsContinuous,
403  .byteSwap = false,
404  .lsbFirst = spiConfig->lsbFirst,
405  .whichPcs = spiConfig->whichPcs,
406  .preDiv = tcrPrescaleValue,
407  .clkPhase = spiConfig->clkPhase,
408  .clkPolarity = spiConfig->clkPolarity
409  };
410  LPSPI_SetTxCommandReg(base, &txCmdCfg);
411  return STATUS_SUCCESS;
412 }
413 
414 /*FUNCTION**********************************************************************
415  *
416  * Function Name : LPSPI_DRV_MasterTransferBlocking
417  * Description : Performs an interrupt driven blocking SPI master mode transfer.
418  *
419  * This function simultaneously sends and receives data on the SPI bus, as SPI is naturally
420  * a full-duplex bus. The function does not return until the transfer is complete.
421  * This function allows the user to optionally pass in a SPI configuration structure which
422  * allows the user to change the SPI bus attributes in conjunction with initiating a SPI transfer.
423  * The difference between passing in the SPI configuration structure here as opposed to the
424  * configure bus function is that the configure bus function returns the calculated baud rate where
425  * this function does not. The user can also call the configure bus function prior to the transfer
426  * in which case the user would simply pass in a NULL to the transfer function's device structure
427  * parameter.
428  * Implements : LPSPI_DRV_MasterTransferBlocking_Activity
429  *
430  *END**************************************************************************/
432  const uint8_t * sendBuffer,
433  uint8_t * receiveBuffer,
434  uint16_t transferByteCount,
435  uint32_t timeout)
436 {
437  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
438  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
439  /* Instantiate local variable of type lpspi_state_t and point to global state */
440  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
441  LPSPI_Type *base = g_lpspiBase[instance];
442  status_t error = STATUS_SUCCESS;
443  status_t osifError;
444  /* If the transfer count is zero, then return immediately.*/
445  if (transferByteCount == (uint16_t)0)
446  {
447  return error;
448  }
449  lpspiState->isBlocking = true;
450  /* start the transfer process, if it returns an error code, return this back to user */
451  error = LPSPI_DRV_MasterStartTransfer(instance, sendBuffer, receiveBuffer,
452  transferByteCount);
453  if (error != STATUS_SUCCESS)
454  {
455  /* The transfer is complete.*/
456  lpspiState->isTransferInProgress = false;
457 
458  /* Disable interrupt requests*/
459  LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, false);
460  LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, false);
461 
463  LPSPI_SetIntMode(base, LPSPI_TRANSFER_COMPLETE, false);
464  (void)LPSPI_ClearStatusFlag(base, LPSPI_TRANSFER_COMPLETE);
465 
466  return error;
467  }
468 
469  /* As this is a synchronous transfer, wait until the transfer is complete.*/
470  osifError = OSIF_SemaWait(&(lpspiState->lpspiSemaphore), timeout);
471 
472  /* If a timeout occurs, stop the transfer by setting the isTransferInProgress to false and
473  * disabling interrupts, then return the timeout error status.
474  */
475  if (osifError == STATUS_TIMEOUT)
476  {
477  /* Set isBlocking variable to false to avoid dummy semaphore post. */
478  lpspiState->isBlocking = false;
479  /* Complete transfer. */
481  return(STATUS_TIMEOUT);
482  }
483 
485  LPSPI_SetIntMode(base, LPSPI_TRANSFER_COMPLETE, false);
486  (void)LPSPI_ClearStatusFlag(base, LPSPI_TRANSFER_COMPLETE);
487 
488  return error;
489 }
490 
491 /*FUNCTION**********************************************************************
492  *
493  * Function Name : LPSPI_DRV_MasterTransfer
494  * Description : Performs an interrupt driven non-blocking SPI master mode transfer.
495  *
496  * This function simultaneously sends and receives data on the SPI bus, as SPI is naturally
497  * a full-duplex bus. The function returns immediately after initiating the transfer. The user
498  * needs to check whether the transfer is complete using the LPSPI_DRV_MasterGetTransferStatus
499  * function.
500  * This function allows the user to optionally pass in a SPI configuration structure which
501  * allows the user to change the SPI bus attributes in conjunction with initiating a SPI transfer.
502  * The difference between passing in the SPI configuration structure here as opposed to the
503  * configure bus function is that the configure bus function returns the calculated baud rate where
504  * this function does not. The user can also call the configure bus function prior to the transfer
505  * in which case the user would simply pass in a NULL to the transfer function's device structure
506  * parameter.
507  * Implements : LPSPI_DRV_MasterTransfer_Activity
508  *
509  *END**************************************************************************/
511  const uint8_t * sendBuffer,
512  uint8_t * receiveBuffer,
513  uint16_t transferByteCount)
514 {
515  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
516  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
517  status_t error = STATUS_SUCCESS;
518  /* If the transfer count is zero, then return immediately.*/
519  if (transferByteCount == (uint16_t)0)
520  {
521  return STATUS_SUCCESS;
522  }
523 
524  /* Start the transfer process, if it returns an error code, return this back to user */
525  error = LPSPI_DRV_MasterStartTransfer(instance, sendBuffer, receiveBuffer,
526  transferByteCount);
527  if (error != STATUS_SUCCESS)
528  {
529  return error;
530  }
531 
532  /* Else, return immediately as this is an async transfer */
533  return STATUS_SUCCESS;
534 }
535 
536 /*FUNCTION**********************************************************************
537  *
538  * Function Name : LPSPI_DRV_MasterGetTransferStatus
539  * Description : Returns whether the previous interrupt driven transfer is completed.
540  *
541  * When performing an a-sync (non-blocking) transfer, the user can call this function to ascertain
542  * the state of the current transfer: in progress (or busy) or complete (success).
543  * In addition, if the transfer is still in progress, the user can get the number of words that
544  * should be receive.
545  * Implements : LPSPI_DRV_MasterGetTransferStatus_Activity
546  *
547  *END**************************************************************************/
548 status_t LPSPI_DRV_MasterGetTransferStatus(uint32_t instance, uint32_t * bytesRemained)
549 {
550  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
551  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
552  /* Instantiate local variable of type lpspi_state_t and point to global state */
553  const lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
554  /* Fill in the bytes transferred.*/
555  if (bytesRemained != NULL)
556  {
557  *bytesRemained = lpspiState->rxCount;
558  }
559  if (lpspiState->status == LPSPI_TRANSFER_OK)
560  {
561  return (status_t)(lpspiState->isTransferInProgress ? STATUS_BUSY : STATUS_SUCCESS);
562  }
563  else
564  {
565  return STATUS_ERROR;
566  }
567 }
568 /*FUNCTION**********************************************************************
569  *
570  * Function Name : LPSPI_DRV_MasterAbortTransfer
571  * Description : Terminates an interrupt driven asynchronous transfer early.
572  *
573  * During an a-sync (non-blocking) transfer, the user has the option to terminate the transfer early
574  * if the transfer is still in progress.
575  * Implements : LPSPI_DRV_MasterAbortTransfer_Activity
576  *END**************************************************************************/
578 {
579  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
580  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
581  LPSPI_Type *base = g_lpspiBase[instance];
582  /* Stop the running transfer. */
584  LPSPI_SetFlushFifoCmd(base, true, true);
585  /* The second flush command is used to avoid the case when one word is still in shifter. */
586  LPSPI_SetFlushFifoCmd(base, true, true);
587  return STATUS_SUCCESS;
588 }
589 
590 /*FUNCTION**********************************************************************
591  *
592  * Function Name : LPSPI_DRV_SetPcs
593  * Description : Select the chip to communicate with.
594  *
595  * The main purpose of this function is to set the PCS and the appropriate polarity.
596  * Implements : LPSPI_DRV_SetPcs_Activity
597  *END**************************************************************************/
598 
600 {
601  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
602  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
603  DEV_ASSERT((uint32_t)whichPcs < 4U);
604 
605  LPSPI_Type *base = g_lpspiBase[instance];
606  status_t result;
607 
608  if (LPSPI_Disable(base) != STATUS_SUCCESS)
609  {
610  return STATUS_ERROR;
611  }
612  result = LPSPI_SetPcsPolarityMode(base, whichPcs, polarity);
613  if (result != STATUS_SUCCESS) {
614  return STATUS_ERROR;
615  }
616  LPSPI_Enable(base);
617  LPSPI_SetPcs(base, whichPcs);
618  return STATUS_SUCCESS;
619 }
620 
621 /*FUNCTION**********************************************************************
622  *
623  * Function Name : LPSPI_DRV_MasterStartTransfer
624  * Description : Configure a non-blocking transfer.
625  *
626  * The number of transferByteCount must be divided by number of bytes/frame.
627  * The sendBuffer must be not NULL, but receiveBuffer can be NULL.
628  *
629  *END**************************************************************************/
630 static status_t LPSPI_DRV_MasterStartTransfer(uint32_t instance,
631  const uint8_t * sendBuffer,
632  uint8_t * receiveBuffer,
633  uint16_t transferByteCount)
634 {
635  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
636  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
637  /* Instantiate local variable of type dspi_master_state_t and point to global state */
638  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
639  LPSPI_Type *base = g_lpspiBase[instance];
641 
642  /* Check that we're not busy. */
643  if (LPSPI_GetStatusFlag(base, LPSPI_MODULE_BUSY))
644  {
645  return STATUS_BUSY;
646  }
647  #ifdef ERRATA_E10655
648  else
649  {
650  /* Double check to fix errata e10655. */
651  if (LPSPI_GetStatusFlag(base, LPSPI_MODULE_BUSY))
652  {
653  return STATUS_BUSY;
654  }
655  }
656  #endif
657 
658  /* Verify if the number of bytes is divided by number of bytes/frame. */
659  if ((transferByteCount % lpspiState->bytesPerFrame) != (uint16_t)0)
660  {
661  return STATUS_ERROR;
662  }
663  if(lpspiState->isPcsContinuous == true)
664  {
665  LPSPI_SetContCBit(base);
666  }
667 
668  /* Configure watermarks */
669  LPSPI_SetRxWatermarks(base, 0U);
670  LPSPI_SetTxWatermarks(base, 2U);
671 
672  lpspiState->status = LPSPI_TRANSFER_OK;
673  /* Clear all interrupts sources */
674  (void)LPSPI_ClearStatusFlag(base, LPSPI_ALL_STATUS);
675  /* Enable fault interrupts sources */
676  LPSPI_SetIntMode(base,LPSPI_TRANSMIT_ERROR , true);
677  if (receiveBuffer != NULL)
678  {
679  LPSPI_SetIntMode(base,LPSPI_RECEIVE_ERROR , true);
680  }
681  if (lpspiState->transferType == LPSPI_USING_INTERRUPTS)
682  {
683  /* Fill out the other members of the run-time state structure. */
684  lpspiState->txBuff = (const uint8_t *)sendBuffer;
685  lpspiState->rxBuff = (uint8_t *)receiveBuffer;
686  lpspiState->txFrameCnt = 0;
687  lpspiState->rxFrameCnt = 0;
688  lpspiState->txCount = transferByteCount;
689  /*For continuous mode an extra word must be written to negate the PCS */
690  if (lpspiState->isPcsContinuous == true)
691  {
692  lpspiState->txCount++;
693  }
694  /* Clean RX and TX buffers */
695  LPSPI_SetFlushFifoCmd(base, true, true);
696  /* The second flush command is used to avoid the case when one word is still in shifter. */
697  LPSPI_SetFlushFifoCmd(base, true, true);
698  /* Update transfer status */
699  lpspiState->isTransferInProgress = true;
700  /* Mask the RX if no buffer is passed in. */
701  if (lpspiState->rxBuff == NULL)
702  {
703  /* Since we're not receiving, set rxCount to 0. */
704  lpspiState->rxCount = 0;
705  }
706  else
707  {
708  /* Enable RDF interrupt if RX buffer is not NULL. */
709  LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, true);
710  lpspiState->rxCount = transferByteCount;
711  }
712  /* Enable the TDF and RDF interrupt. */
713  LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, true);
714  }
715  else
716  {
717  /* Configure rxCount depending on transfer type.*/
718  if (receiveBuffer == NULL)
719  {
720  lpspiState->rxCount = 0;
721  }
722  else
723  {
724  lpspiState->rxCount = transferByteCount;
725  }
726 
727  /* When LPSPI use DMA frames with 3 bytes size are not accepted. */
728  switch(lpspiState->bytesPerFrame)
729  {
730  case 1: dmaTransferSize = EDMA_TRANSFER_SIZE_1B; break;
731  case 2: dmaTransferSize = EDMA_TRANSFER_SIZE_2B; break;
732  case 4: dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
733  default : dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
734  }
735  /* Configure TX DMA channel */
736  if (sendBuffer != NULL)
737  {
739  (uint32_t)sendBuffer, (uint32_t)(&(base->TDR)), dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
740  (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
741  }
742  else
743  {
745  (uint32_t)(&(lpspiState->dummy)), (uint32_t)(&(base->TDR)), dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
746  (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
747  }
748  /* Start TX channel */
749  (void)EDMA_DRV_StartChannel(lpspiState->txDMAChannel);
750  /* Configure RX DMA channel if is used in current transfer. */
751  if(receiveBuffer != NULL)
752  {
754  (uint32_t)(&(base->RDR)),(uint32_t)receiveBuffer, dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
755  (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
756 
757  (void)EDMA_DRV_InstallCallback(lpspiState->rxDMAChannel, (LPSPI_DRV_MasterCompleteDMATransfer),(void*)(instance));
758  if (lpspiState->isPcsContinuous == true)
759  {
760  (void)EDMA_DRV_InstallCallback(lpspiState->txDMAChannel, (LPSPI_DRV_MasterClearCountinuous),(void*)(instance));
761  }
762  /* Start RX channel */
763  (void)EDMA_DRV_StartChannel(lpspiState->rxDMAChannel);
764  }
765  else
766  {
767  /* If RX buffer is null the transfer is done when all bytes were sent. */
768  (void)EDMA_DRV_InstallCallback(lpspiState->txDMAChannel, (LPSPI_DRV_MasterCompleteDMATransfer),(void*)(instance));
769  }
770  /* Update transfer status */
771  lpspiState->isTransferInProgress = true;
772  /* Enable LPSPI DMA request */
773  if (receiveBuffer!=NULL)
774  {
775  LPSPI_SetRxDmaCmd(base, true);
776  }
777  LPSPI_SetTxDmaCmd(base, true);
778  }
779  return STATUS_SUCCESS;
780 }
781 
787 static void LPSPI_DRV_MasterCompleteTransfer(uint32_t instance)
788 {
789  /* instantiate local variable of type dspi_master_state_t and point to global state */
790  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
791  LPSPI_Type *base = g_lpspiBase[instance];
792  /* The transfer is complete.*/
793  lpspiState->isTransferInProgress = false;
794  if(lpspiState->transferType == LPSPI_USING_DMA)
795  {
796  /* Disable LPSPI DMA request */
797  LPSPI_SetRxDmaCmd(base, false);
798  LPSPI_SetTxDmaCmd(base, false);
799  }
800  else
801  {
802  /* Disable (clear) interrupt requests */
803  LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, false);
804  LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, false);
805  }
806 
808  LPSPI_SetIntMode(base, LPSPI_TRANSFER_COMPLETE, false);
809  (void)LPSPI_ClearStatusFlag(base, LPSPI_TRANSFER_COMPLETE);
810  if (lpspiState->isBlocking == true)
811  {
812  (void)OSIF_SemaPost(&(lpspiState->lpspiSemaphore));
813  lpspiState->isBlocking = false;
814  }
815  if (lpspiState->callback != NULL)
816  {
817  lpspiState->callback(lpspiState, SPI_EVENT_END_TRANSFER, lpspiState->callbackParam);
818  }
819 
820 }
821 
826 static void LPSPI_DRV_MasterCompleteDMATransfer(void* parameter, edma_chn_status_t status)
827 {
828  uint32_t instance = (uint32_t)parameter;
829 
830  (void)status;
831  /* Disable continuous PCS */
833 }
834 
839 static void LPSPI_DRV_MasterClearCountinuous(void* parameter, edma_chn_status_t status)
840 {
841  uint32_t instance = (uint32_t)parameter;
842  LPSPI_Type *base = g_lpspiBase[instance];
843 
844  (void)status;
845  /* Disable continuous PCS */
846  LPSPI_ClearContCBit(base);
847 }
848 
854 void LPSPI_DRV_MasterIRQHandler(uint32_t instance)
855 {
856  /* Instantiate local variable of type dspi_master_state_t and point to global state */
857  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
858  LPSPI_Type *base = g_lpspiBase[instance];
859  uint16_t txCount, rxCount;
860  txCount = lpspiState->txCount;
861  rxCount = lpspiState->rxCount;
862 
863  /* If an error is detected the transfer will be aborted */
864  if ((bool)LPSPI_GetStatusFlag(base, LPSPI_TRANSMIT_ERROR) && (lpspiState->txBuff != NULL))
865  {
866  lpspiState->status = LPSPI_TRANSMIT_FAIL;
867  (void)LPSPI_DRV_MasterAbortTransfer(instance);
868  (void)LPSPI_ClearStatusFlag(base, LPSPI_TRANSMIT_ERROR);
869  return;
870  }
871  if (LPSPI_GetStatusFlag(base, LPSPI_RECEIVE_ERROR) && (lpspiState->rxBuff != NULL))
872  {
873  lpspiState->status = LPSPI_RECEIVE_FAIL;
874  (void)LPSPI_DRV_MasterAbortTransfer(instance);
875  (void)LPSPI_ClearStatusFlag(base, LPSPI_RECEIVE_ERROR);
876  return;
877  }
878 
879  /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */
880  if(LPSPI_GetStatusFlag(base,LPSPI_RX_DATA_FLAG) && (rxCount != (uint16_t)0))
881  {
882  LPSPI_DRV_ReadRXBuffer(instance);
883  }
884  /* Transmit data */
885  if (LPSPI_GetStatusFlag(base,LPSPI_TX_DATA_FLAG) && ((txCount != (uint16_t)0)))
886  {
887  LPSPI_DRV_FillupTxBuffer(instance);
888  }
889  txCount = lpspiState->txCount;
890  rxCount = lpspiState->rxCount;
891  if (txCount == (uint16_t)0)
892  {
893  /* Disable TX flag. Software buffer is empty.*/
894  LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, false);
895  LPSPI_SetIntMode(base, LPSPI_TRANSFER_COMPLETE, true);
896  /* Check if we're done with this transfer.*/
897  if (rxCount == (uint16_t)0)
898  {
899  if (LPSPI_GetStatusFlag(base, LPSPI_TRANSFER_COMPLETE) == true)
900  {
902  }
903  }
904  }
905 }
906 
907 /*******************************************************************************
908  * EOF
909  ******************************************************************************/
volatile uint16_t rxFrameCnt
#define LPSPI_INSTANCE_COUNT
Definition: S32K118.h:6049
volatile uint16_t txFrameCnt
Runtime state structure for the LPSPI master driver.
Data structure containing information about a device on the SPI bus.
void LPSPI_DRV_ReadRXBuffer(uint32_t instance)
The function LPSPI_DRV_ReadRXBuffer reads data from RX hardware buffer and writes this data in RX sof...
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
volatile const uint32_t RDR
Definition: S32K118.h:6045
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
lpspi_signal_polarity_t pcsPolarity
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 LPSPI_DRV_SetPcs(uint32_t instance, lpspi_which_pcs_t whichPcs, lpspi_signal_polarity_t polarity)
Select the chip to communicate with.
LPSPI_Type * g_lpspiBase[(2u)]
Table of base pointers for SPI instances.
status_t LPSPI_DRV_MasterDeinit(uint32_t instance)
Shuts down a LPSPI instance.
lpspi_transfer_type transferType
lpspi_transfer_type transferType
spi_callback_t callback
static void LPSPI_DRV_MasterCompleteTransfer(uint32_t instance)
Finish up a transfer. Cleans up after a transfer is complete. Interrupts are disabled, and the LPSPI module is disabled. This is not a public API as it is called from other driver functions.
status_t LPSPI_DRV_MasterConfigureBus(uint32_t instance, const lpspi_master_config_t *spiConfig, uint32_t *calculatedBaudRate)
Configures the LPSPI port physical parameters to access a device on the bus when the LSPI instance is...
status_t LPSPI_DRV_MasterInit(uint32_t instance, lpspi_state_t *lpspiState, const lpspi_master_config_t *spiConfig)
Initializes a LPSPI instance for interrupt driven master mode operation.
status_t LPSPI_DRV_MasterTransfer(uint32_t instance, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount)
Performs an interrupt driven non-blocking SPI master mode transfer.
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
status_t LPSPI_DRV_MasterGetTransferStatus(uint32_t instance, uint32_t *bytesRemained)
Returns whether the previous interrupt driven transfer is completed.
void LPSPI_DRV_FillupTxBuffer(uint32_t instance)
The function LPSPI_DRV_FillupTxBuffer writes data in TX hardware buffer depending on driver state and...
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
#define DEV_ASSERT(x)
Definition: devassert.h:77
volatile uint16_t rxCount
void LPSPI_DRV_MasterIRQHandler(uint32_t instance)
Interrupt handler for LPSPI master mode. This handler uses the buffers stored in the lpspi_state_t st...
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
lpspi_clock_phase_t clkPhase
volatile uint16_t txCount
status_t LPSPI_DRV_MasterTransferBlocking(uint32_t instance, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount, uint32_t timeout)
Performs an interrupt driven blocking SPI master mode transfer.
status_t LPSPI_DRV_MasterSetDelay(uint32_t instance, uint32_t delayBetwenTransfers, uint32_t delaySCKtoPCS, uint32_t delayPCStoSCK)
Configures the LPSPI master mode bus timing delay options.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
lpspi_signal_polarity_t
LPSPI Signal (PCS and Host Request) Polarity configuration. Implements : lpspi_signal_polarity_t_Clas...
lpspi_which_pcs_t
LPSPI Peripheral Chip Select (PCS) configuration (which PCS to configure). Implements : lpspi_which_p...
void LPSPI_DRV_DisableTEIEInterrupts(uint32_t instance)
Disable the TEIE interrupts at the end of a transfer. Disable the interrupts and clear the status for...
static status_t LPSPI_DRV_MasterStartTransfer(uint32_t instance, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount)
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
lpspi_which_pcs_t whichPcs
static void LPSPI_DRV_MasterCompleteDMATransfer(void *parameter, edma_chn_status_t status)
Finish up a transfer DMA. The main purpose of this function is to create a function compatible with D...
volatile bool isTransferInProgress
lpspi_state_t * g_lpspiStatePtr[(2u)]
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
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
status_t LPSPI_DRV_MasterAbortTransfer(uint32_t instance)
Terminates an interrupt driven asynchronous transfer early.
lpspi_sck_polarity_t clkPolarity
#define MICROSECONDS
const uint8_t * txBuff
volatile uint32_t TDR
Definition: S32K118.h:6042
semaphore_t lpspiSemaphore
IRQn_Type g_lpspiIrqId[(2u)]
Table to save LPSPI IRQ enumeration numbers defined in the CMSIS header file.
static void LPSPI_DRV_MasterClearCountinuous(void *parameter, edma_chn_status_t status)
Clear the continuous mode. The main purpose of this function is to clear continuous mode...
transfer_status_t status