S32 SDK
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 "lpspi_shared_function.h"
92 #include "S32K144_features.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  LPSPI_Type *base = g_lpspiBase[instance];
147  status_t errorCode = STATUS_SUCCESS;
148 
149  /* Save runtime structure pointers so irq handler can point to the correct state structure */
150  g_lpspiStatePtr[instance] = lpspiState;
151  /* Reset the LPSPI registers to their default state */
152  LPSPI_HAL_Init(base);
153  /* Set for master mode */
155  /* Set Pin configuration such that SDO=out and SDI=in */
157  /* Calculate the FIFO size for the LPSPI */
158  LPSPI_HAL_GetFifoSizes(base, &(lpspiState->fifoSize), NULL);
159 
160  /* Configure bus for this device. If NULL is passed, we assume the caller has
161  * preconfigured the bus and doesn't wish to re-configure it again for this transfer.
162  * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate
163  * then they can call this function separately.
164  */
165  errorCode = LPSPI_DRV_MasterConfigureBus(instance, spiConfig, NULL);
166  if (errorCode != STATUS_SUCCESS)
167  {
168  return errorCode;
169  }
170  /* Initialize the semaphore */
171  errorCode = OSIF_SemaCreate(&(lpspiState->lpspiSemaphore), 0);
172  DEV_ASSERT(errorCode == STATUS_SUCCESS);
173  /* Enable the interrupt */
174  INT_SYS_EnableIRQ(g_lpspiIrqId[instance]);
175  /* Finally, enable LPSPI */
176  LPSPI_HAL_Enable(base);
177  return errorCode;
178 }
179 
180 /*FUNCTION**********************************************************************
181  *
182  * Function Name : LPSPI_DRV_MasterDeinit
183  * Description : Shuts down a LPSPI instance.
184  *
185  * This function resets the LPSPI peripheral, gates its clock, and disables the interrupt to
186  * the core. It first checks to see if a transfer is in progress and if so returns an error
187  * status.
188  * Implements : LPSPI_DRV_MasterDeinit_Activity
189  *
190  *END**************************************************************************/
192 {
193  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
194  /* Instantiate local variable of type lpspi_state_t and point to global state */
195  const lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
196  LPSPI_Type *base = g_lpspiBase[instance];
197  status_t errorCode = STATUS_SUCCESS;
198 
199  /* Check if a transfer is still in progress */
200  DEV_ASSERT(lpspiState->isTransferInProgress == false);
201 
202  /* Reset the LPSPI registers to their default state, inlcuding disabling the LPSPI */
203  LPSPI_HAL_Init(base);
204  /* Disable the interrupt */
205  INT_SYS_DisableIRQ(g_lpspiIrqId[instance]);
206  /* Clear the state pointer. */
207  g_lpspiStatePtr[instance] = NULL;
208 
209  /* Destroy the semaphore */
210  errorCode = OSIF_SemaDestroy(&(lpspiState->lpspiSemaphore));
211  DEV_ASSERT(errorCode == STATUS_SUCCESS);
212  return errorCode;
213 }
214 
215 /*FUNCTION**********************************************************************
216  *
217  * Function Name : LPSPI_DRV_MasterSetDelay
218  * Description : Configures the LPSPI master mode bus timing delay options.
219  *
220  * This function involves the LPSPI module's delay options to
221  * "fine tune" some of the signal timings and match the timing needs of a slower peripheral device.
222  * This is an optional function that can be called after the LPSPI module has been initialized for
223  * master mode. The timings are adjusted in terms of cycles of the baud rate clock.
224  * The bus timing delays that can be adjusted are listed below:
225  *
226  * SCK to PCS Delay: Adjustable delay option between the last edge of SCK to the de-assertion
227  * of the PCS signal.
228  *
229  * PCS to SCK Delay: Adjustable delay option between the assertion of the PCS signal to the
230  * first SCK edge.
231  *
232  * Delay between Transfers: Adjustable delay option between the de-assertion of the PCS signal for
233  * a frame to the assertion of the PCS signal for the next frame.
234  * Implements : LPSPI_DRV_MasterSetDelay_Activity
235  *
236  *END**************************************************************************/
237 status_t LPSPI_DRV_MasterSetDelay(uint32_t instance, uint32_t delayBetwenTransfers,
238  uint32_t delaySCKtoPCS, uint32_t delayPCStoSCK)
239 {
240  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
241  /* Instantiate local variable of type lpspi_state_t and point to global state */
242  const lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
243  LPSPI_Type *base = g_lpspiBase[instance];
244  status_t errorCode = STATUS_SUCCESS;
245  uint32_t realDelayBetwenTransfers, realDelaySCKtoPCS, realDelayPCStoSCK;
246  lpspi_prescaler_t prescaler;
247  /* Disable module */
248  errorCode = LPSPI_HAL_Disable(base);
249  if (errorCode != STATUS_SUCCESS)
250  {
251  return errorCode;
252  }
253  prescaler = LPSPI_HAL_GetClockPrescaler(base);
254  realDelayBetwenTransfers = delayBetwenTransfers * lpspiState->lpspiSrcClk / s_baudratePrescaler[prescaler] / (uint32_t)MICROSECONDS;
255  realDelaySCKtoPCS = delaySCKtoPCS * lpspiState->lpspiSrcClk / s_baudratePrescaler[prescaler] / (uint32_t)MICROSECONDS;
256  realDelayPCStoSCK = delayPCStoSCK * lpspiState->lpspiSrcClk/ s_baudratePrescaler[prescaler] / (uint32_t)MICROSECONDS;
257  /* Verify if current prescaler can be used for this configuration of delays
258  * If a delay is out of range, it will be adjusted to min or max value */
259  if (realDelayBetwenTransfers > (uint32_t)257U)
260  {
261  realDelayBetwenTransfers = (uint32_t)257U;
262  }
263  if(realDelaySCKtoPCS > (uint32_t)256U)
264  {
265  realDelaySCKtoPCS = (uint32_t)256U;
266  }
267  if(realDelayPCStoSCK > (uint32_t)256U)
268  {
269  realDelayPCStoSCK = (uint32_t)256U;
270  }
271  if (realDelayBetwenTransfers < (uint32_t)2U)
272  {
273  realDelayBetwenTransfers = (uint32_t)2U;
274  }
275  if(realDelaySCKtoPCS == (uint32_t)0)
276  {
277  realDelaySCKtoPCS = (uint32_t)1U;
278  }
279  if(realDelayPCStoSCK == (uint32_t)0U)
280  {
281  realDelayPCStoSCK = (uint32_t)1U;
282  }
283 
284  (void)LPSPI_HAL_SetDelay(base, LPSPI_SCK_TO_PCS, realDelaySCKtoPCS-1U);
285  (void)LPSPI_HAL_SetDelay(base, LPSPI_PCS_TO_SCK, realDelayPCStoSCK-1U);
286  (void)LPSPI_HAL_SetDelay(base, LPSPI_BETWEEN_TRANSFER, realDelayBetwenTransfers-2U);
287  /* Enable module */
288  LPSPI_HAL_Enable(base);
289  return errorCode;
290 }
291 
292 /*FUNCTION**********************************************************************
293  *
294  * Function Name : LPSPI_DRV_MasterConfigureBus
295  * Description : Configures the LPSPI port physical parameters to access a device on the bus when
296  * the LSPI instance is configured for interrupt operation.
297  *
298  * In this function, the term "spiConfig" is used to indicate the SPI device for which the LPSPI
299  * master is communicating. This is an optional function as the spiConfig parameters are
300  * normally configured in the initialization function or the transfer functions, where these various
301  * functions would call the configure bus function.
302  * The user can pass in a different spiConfig structure to the transfer function which contains
303  * the parameters for the SPI bus to allow for communication to a different SPI device
304  * (the transfer function then calls this function). However, the user also has the option to call
305  * this function directly especially to get the calculated baud rate, at which point they may pass
306  * in NULL for the spiConfig structure in the transfer function (assuming they have called this
307  * configure bus function first).
308  * Implements : LPSPI_DRV_MasterConfigureBus_Activity
309  *
310  *END**************************************************************************/
312  const lpspi_master_config_t * spiConfig,
313  uint32_t * calculatedBaudRate)
314 {
315  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
316  DEV_ASSERT(spiConfig != NULL);
317  /* Instantiate local variable of type lpspi_state_t and point to global state */
318  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
319  LPSPI_Type *base = g_lpspiBase[instance];
320  uint32_t baudRate;
321 
322  /* The Transmit Command Register (TCR) Prescale value is calculated as part of the baud rate
323  calculation. The value is stored in the run-time state structure for later programming
324  in the TCR. */
325  uint32_t tcrPrescaleValue;
326 
327  /* Check the bitcount to make sure it falls within the boundary conditions */
328  if ((spiConfig->bitcount < 8U) || (spiConfig->bitcount > 4096U))
329  {
330  return STATUS_ERROR;
331  }
332  /* First, per the spec, we need to disable the LPSPI module before setting the delay */
333 
334  if (LPSPI_HAL_Disable(base) != STATUS_SUCCESS)
335  {
336  /* If error is returned, the LPSPI is busy */
337  return STATUS_ERROR;
338  }
339  /* Configure internal state structure for LPSPI */
340  lpspiState->bitsPerFrame = spiConfig->bitcount;
341  lpspiState->lpspiSrcClk = spiConfig->lpspiSrcClk;
342  lpspiState->isPcsContinuous = spiConfig->isPcsContinuous;
343  lpspiState->lsb = spiConfig->lsbFirst;
344  /* Save transfer type DMA/Interrupt */
345  lpspiState->transferType = spiConfig->transferType;
346  /* Update transfer status */
347  lpspiState->isTransferInProgress = false;
348  lpspiState->isBlocking = false;
349  /* Calculate the bytes/frame for lpspiState->bytesPerFrame. */
350  lpspiState->bytesPerFrame = (uint16_t)((lpspiState->bitsPerFrame + 7U) / 8U);
351  /* For DMA transfers bytes per frame must be equal to 1, 2 or multiple of 4 */
352  if ((lpspiState->transferType == LPSPI_USING_DMA) && (!(((lpspiState->bytesPerFrame % 4U) == (uint16_t)0) ||
353  (lpspiState->bytesPerFrame<=2U))))
354  {
355  return STATUS_ERROR;
356  }
357  /* Store DMA channel number used in transfer */
358  lpspiState->rxDMAChannel = spiConfig->rxDMAChannel;
359  lpspiState->txDMAChannel = spiConfig->txDMAChannel;
360 
361  /* Configure the desired PCS polarity */
362  (void)LPSPI_HAL_SetPcsPolarityMode(base, spiConfig->whichPcs, spiConfig->pcsPolarity);
363 
364 
365  /* Set up the baud rate */
366  baudRate = LPSPI_HAL_SetBaudRate(base, spiConfig->bitsPerSec, spiConfig->lpspiSrcClk,
367  &tcrPrescaleValue);
368 
369  /* Now, re-enable the LPSPI module */
370  LPSPI_HAL_Enable(base);
371 
372  /* If the baud rate return is "0", it means there was an error */
373  if (baudRate == (uint32_t)0)
374  {
375  return STATUS_ERROR;
376  }
377 
378  /* If the user wishes to know the calculated baud rate, then pass it back */
379  if (calculatedBaudRate != NULL)
380  {
381  *calculatedBaudRate = baudRate;
382  }
383  /* Write the TCR for this transfer. */
384  lpspi_tx_cmd_config_t txCmdCfg =
385  {
386  .frameSize = lpspiState->bitsPerFrame,
387  .width = LPSPI_SINGLE_BIT_XFER,
388  .txMask = false,
389  .rxMask = false,
390  .contCmd = false,
391  .contTransfer = spiConfig->isPcsContinuous,
392  .byteSwap = false,
393  .lsbFirst = spiConfig->lsbFirst,
394  .whichPcs = spiConfig->whichPcs,
395  .preDiv = tcrPrescaleValue,
396  .clkPhase = spiConfig->clkPhase,
397  .clkPolarity = spiConfig->clkPolarity
398  };
399  LPSPI_HAL_SetTxCommandReg(base, &txCmdCfg);
400  return STATUS_SUCCESS;
401 }
402 
403 /*FUNCTION**********************************************************************
404  *
405  * Function Name : LPSPI_DRV_MasterTransferBlocking
406  * Description : Performs an interrupt driven blocking SPI master mode transfer.
407  *
408  * This function simultaneously sends and receives data on the SPI bus, as SPI is naturally
409  * a full-duplex bus. The function does not return until the transfer is complete.
410  * This function allows the user to optionally pass in a SPI configuration structure which
411  * allows the user to change the SPI bus attributes in conjunction with initiating a SPI transfer.
412  * The difference between passing in the SPI configuration structure here as opposed to the
413  * configure bus function is that the configure bus function returns the calculated baud rate where
414  * this function does not. The user can also call the configure bus function prior to the transfer
415  * in which case the user would simply pass in a NULL to the transfer function's device structure
416  * parameter.
417  * Implements : LPSPI_DRV_MasterTransferBlocking_Activity
418  *
419  *END**************************************************************************/
421  const uint8_t * sendBuffer,
422  uint8_t * receiveBuffer,
423  uint16_t transferByteCount,
424  uint32_t timeout)
425 {
426  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
427  /* Instantiate local variable of type lpspi_state_t and point to global state */
428  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
429  LPSPI_Type *base = g_lpspiBase[instance];
430  status_t error = STATUS_SUCCESS;
431  status_t osifError;
432  /* If the transfer count is zero, then return immediately.*/
433  if (transferByteCount == (uint16_t)0)
434  {
435  return error;
436  }
437  lpspiState->isBlocking = true;
438  /* start the transfer process, if it returns an error code, return this back to user */
439  error = LPSPI_DRV_MasterStartTransfer(instance, sendBuffer, receiveBuffer,
440  transferByteCount);
441  if (error != STATUS_SUCCESS)
442  {
443  /* The transfer is complete.*/
444  lpspiState->isTransferInProgress = false;
445  /* Disable interrupt requests*/
446  /*LPSPI_CLR_IER(base, LPSPI_IER_TDIE_MASK|LPSPI_IER_RDIE_MASK);*/
449 
453 
454  return error;
455  }
456 
457  /* As this is a synchronous transfer, wait until the transfer is complete.*/
458  osifError = OSIF_SemaWait(&(lpspiState->lpspiSemaphore), timeout);
459 
460  /* If a timeout occurs, stop the transfer by setting the isTransferInProgress to false and
461  * disabling interrupts, then return the timeout error status.
462  */
463  if (osifError == STATUS_TIMEOUT)
464  {
465  /* Set isBlocking variable to false to avoid dummy semaphore post. */
466  lpspiState->isBlocking = false;
467  /* Complete transfer. */
469  return(STATUS_TIMEOUT);
470  }
471 
475 
476  return error;
477 }
478 
479 /*FUNCTION**********************************************************************
480  *
481  * Function Name : LPSPI_DRV_MasterTransfer
482  * Description : Performs an interrupt driven non-blocking SPI master mode transfer.
483  *
484  * This function simultaneously sends and receives data on the SPI bus, as SPI is naturally
485  * a full-duplex bus. The function returns immediately after initiating the transfer. The user
486  * needs to check whether the transfer is complete using the LPSPI_DRV_MasterGetTransferStatus
487  * function.
488  * This function allows the user to optionally pass in a SPI configuration structure which
489  * allows the user to change the SPI bus attributes in conjunction with initiating a SPI transfer.
490  * The difference between passing in the SPI configuration structure here as opposed to the
491  * configure bus function is that the configure bus function returns the calculated baud rate where
492  * this function does not. The user can also call the configure bus function prior to the transfer
493  * in which case the user would simply pass in a NULL to the transfer function's device structure
494  * parameter.
495  * Implements : LPSPI_DRV_MasterTransfer_Activity
496  *
497  *END**************************************************************************/
499  const uint8_t * sendBuffer,
500  uint8_t * receiveBuffer,
501  uint16_t transferByteCount)
502 {
503  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
504  status_t error = STATUS_SUCCESS;
505  /* If the transfer count is zero, then return immediately.*/
506  if (transferByteCount == (uint16_t)0)
507  {
508  return STATUS_SUCCESS;
509  }
510 
511  /* Start the transfer process, if it returns an error code, return this back to user */
512  error = LPSPI_DRV_MasterStartTransfer(instance, sendBuffer, receiveBuffer,
513  transferByteCount);
514  if (error != STATUS_SUCCESS)
515  {
516  return error;
517  }
518 
519  /* Else, return immediately as this is an async transfer */
520  return STATUS_SUCCESS;
521 }
522 
523 /*FUNCTION**********************************************************************
524  *
525  * Function Name : LPSPI_DRV_MasterGetTransferStatus
526  * Description : Returns whether the previous interrupt driven transfer is completed.
527  *
528  * When performing an a-sync (non-blocking) transfer, the user can call this function to ascertain
529  * the state of the current transfer: in progress (or busy) or complete (success).
530  * In addition, if the transfer is still in progress, the user can get the number of words that
531  * should be receive.
532  * Implements : LPSPI_DRV_MasterGetTransferStatus_Activity
533  *
534  *END**************************************************************************/
535 status_t LPSPI_DRV_MasterGetTransferStatus(uint32_t instance, uint32_t * bytesRemained)
536 {
537  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
538  /* Instantiate local variable of type lpspi_state_t and point to global state */
539  const lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
540  /* Fill in the bytes transferred.*/
541  if (bytesRemained != NULL)
542  {
543  *bytesRemained = lpspiState->rxCount;
544  }
545  if (lpspiState->status == LPSPI_TRANSFER_OK)
546  {
547  return (status_t)(lpspiState->isTransferInProgress ? STATUS_BUSY : STATUS_SUCCESS);
548  }
549  else
550  {
551  return STATUS_ERROR;
552  }
553 }
554 /*FUNCTION**********************************************************************
555  *
556  * Function Name : LPSPI_DRV_MasterAbortTransfer
557  * Description : Terminates an interrupt driven asynchronous transfer early.
558  *
559  * During an a-sync (non-blocking) transfer, the user has the option to terminate the transfer early
560  * if the transfer is still in progress.
561  * Implements : LPSPI_DRV_MasterAbortTransfer_Activity
562  *END**************************************************************************/
564 {
565  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
566  LPSPI_Type *base = g_lpspiBase[instance];
567  /* Stop the running transfer. */
569  LPSPI_HAL_SetFlushFifoCmd(base, true, true);
570  /* The second flush command is used to avoid the case when one word is still in shifter. */
571  LPSPI_HAL_SetFlushFifoCmd(base, true, true);
572  return STATUS_SUCCESS;
573 }
574 
575 /*FUNCTION**********************************************************************
576  *
577  * Function Name : LPSPI_DRV_MasterStartTransfer
578  * Description : Configure a non-blocking transfer.
579  *
580  * The number of transferByteCount must be divided by number of bytes/frame.
581  * The sendBuffer must be not NULL, but receiveBuffer can be NULL.
582  *
583  *END**************************************************************************/
584 static status_t LPSPI_DRV_MasterStartTransfer(uint32_t instance,
585  const uint8_t * sendBuffer,
586  uint8_t * receiveBuffer,
587  uint16_t transferByteCount)
588 {
589  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
590  DEV_ASSERT(sendBuffer != NULL);
591  /* Instantiate local variable of type dspi_master_state_t and point to global state */
592  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
593  LPSPI_Type *base = g_lpspiBase[instance];
596 
597  /* Check that we're not busy. */
599  {
600  return STATUS_BUSY;
601  }
602  #ifdef ERRATA_E10655
603  else
604  {
605  /* Double check to fix errata e10655. */
607  {
608  return STATUS_BUSY;
609  }
610  }
611  #endif
612 
613  /* Verify if the number of bytes is divided by number of bytes/frame. */
614  if ((transferByteCount % lpspiState->bytesPerFrame) != (uint16_t)0)
615  {
616  return STATUS_ERROR;
617  }
618  if(lpspiState->isPcsContinuous == true)
619  {
620  LPSPI_HAL_SetContCBit(base);
621  }
622 
623  /* Configure watermarks */
624  LPSPI_HAL_SetRxWatermarks(base, 0U);
625  LPSPI_HAL_SetTxWatermarks(base, 2U);
626 
627  lpspiState->status = LPSPI_TRANSFER_OK;
628  /* Clear all interrupts sources */
630  /* Enable fault interrupts sources */
633 
634  if (lpspiState->transferType == LPSPI_USING_INTERRUPTS)
635  {
636  /* Fill out the other members of the run-time state structure. */
637  lpspiState->txBuff = (const uint8_t *)sendBuffer;
638  lpspiState->rxBuff = (uint8_t *)receiveBuffer;
639  lpspiState->txFrameCnt = 0;
640  lpspiState->rxFrameCnt = 0;
641  lpspiState->txCount = transferByteCount;
642  /*For continuous mode an extra word must be written to negate the PCS */
643  if (lpspiState->isPcsContinuous == true)
644  {
645  lpspiState->txCount++;
646  }
647  /* Clean RX and TX buffers */
648  LPSPI_HAL_SetFlushFifoCmd(base, true, true);
649  /* The second flush command is used to avoid the case when one word is still in shifter. */
650  LPSPI_HAL_SetFlushFifoCmd(base, true, true);
651  /* Update transfer status */
652  lpspiState->isTransferInProgress = true;
653  /* Mask the RX if no buffer is passed in. */
654  if (lpspiState->rxBuff == NULL)
655  {
656  /* Since we're not receiving, set rxCount to 0. */
657  lpspiState->rxCount = 0;
658  }
659  else
660  {
661  /* Enable RDF interrupt if RX buffer is not NULL. */
663  lpspiState->rxCount = transferByteCount;
664  }
665  /* Enable the TDF and RDF interrupt. */
667  }
668  else
669  {
670  /* Configure rxCount depending on transfer type.*/
671  if (receiveBuffer == NULL)
672  {
673  lpspiState->rxCount = 0;
674  }
675  else
676  {
677  lpspiState->rxCount = transferByteCount;
678  }
679 
680  /* When LPSPI use DMA frames with 3 bytes size are not accepted. */
681  switch(lpspiState->bytesPerFrame)
682  {
683  case 1: dmaTransferSize = EDMA_TRANSFER_SIZE_1B; break;
684  case 2: dmaTransferSize = EDMA_TRANSFER_SIZE_2B; break;
685  case 4: dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
686  default : dmaTransferSize = EDMA_TRANSFER_SIZE_1B; break;
687  }
688  /* Configure TX DMA channel */
690  (uint32_t)sendBuffer, (uint32_t)(&(base->TDR)), dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize));
691  EDMA_HAL_TCDSetMajorCount(baseDma, lpspiState->txDMAChannel, (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)));
692  /* Disable DMA requests for TX channel when transfer is done. */
694  /* Start TX channel */
695  (void)EDMA_DRV_StartChannel(lpspiState->txDMAChannel);
696  /* Configure RX DMA channel if is used in current transfer. */
697  if(receiveBuffer != NULL)
698  {
700  (uint32_t)(&(base->RDR)),(uint32_t)receiveBuffer, dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize));
701  EDMA_HAL_TCDSetMajorCount(baseDma, lpspiState->rxDMAChannel, (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)));
702  /* Transfer is done when all bytes were received. */
703 
704  (void)EDMA_DRV_InstallCallback(lpspiState->rxDMAChannel, (LPSPI_DRV_MasterCompleteDMATransfer),(void*)(instance));
705  if (lpspiState->isPcsContinuous == true)
706  {
707  (void)EDMA_DRV_InstallCallback(lpspiState->txDMAChannel, (LPSPI_DRV_MasterClearCountinuous),(void*)(instance));
708  }
709  /* Disable DMA requests for RX channel when transfer is done. */
711  /* Start RX channel */
712  (void)EDMA_DRV_StartChannel(lpspiState->rxDMAChannel);
713  }
714  else
715  {
716  /* If RX buffer is null the transfer is done when all bytes were sent. */
717  (void)EDMA_DRV_InstallCallback(lpspiState->txDMAChannel, (LPSPI_DRV_MasterCompleteDMATransfer),(void*)(instance));
718  }
719  /* Update transfer status */
720  lpspiState->isTransferInProgress = true;
721  /* Enable LPSPI DMA request */
722  if (receiveBuffer!=NULL)
723  {
724  LPSPI_HAL_SetRxDmaCmd(base, true);
725  }
726  LPSPI_HAL_SetTxDmaCmd(base, true);
727  }
728  return STATUS_SUCCESS;
729 }
730 
736 static void LPSPI_DRV_MasterCompleteTransfer(uint32_t instance)
737 {
738  /* instantiate local variable of type dspi_master_state_t and point to global state */
739  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
740  LPSPI_Type *base = g_lpspiBase[instance];
741  /* The transfer is complete.*/
742  lpspiState->isTransferInProgress = false;
743  if(lpspiState->transferType == LPSPI_USING_DMA)
744  {
745  /* Disable LPSPI DMA request */
746  LPSPI_HAL_SetRxDmaCmd(base, false);
747  LPSPI_HAL_SetTxDmaCmd(base, false);
748  }
749  else
750  {
751  /* Disable (clear) interrupt requests */
754  }
755 
759  if (lpspiState->isBlocking == true)
760  {
761  (void)OSIF_SemaPost(&(lpspiState->lpspiSemaphore));
762  lpspiState->isBlocking = false;
763  }
764 
765 }
766 
771 static void LPSPI_DRV_MasterCompleteDMATransfer(void* parameter, edma_chn_status_t status)
772 {
773  uint32_t instance = (uint32_t)parameter;
774 
775  (void)status;
776  /* Disable continuous PCS */
778 }
779 
784 static void LPSPI_DRV_MasterClearCountinuous(void* parameter, edma_chn_status_t status)
785 {
786  uint32_t instance = (uint32_t)parameter;
787  LPSPI_Type *base = g_lpspiBase[instance];
788 
789  (void)status;
790  /* Disable continuous PCS */
792 }
793 
799 void LPSPI_DRV_MasterIRQHandler(uint32_t instance)
800 {
801  /* Instantiate local variable of type dspi_master_state_t and point to global state */
802  lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
803  LPSPI_Type *base = g_lpspiBase[instance];
804  uint16_t txCount, rxCount;
805  txCount = lpspiState->txCount;
806  rxCount = lpspiState->rxCount;
807 
808  /* If an error is detected the transfer will be aborted */
810  {
811  lpspiState->status = LPSPI_TRANSMIT_FAIL;
812  (void)LPSPI_DRV_MasterAbortTransfer(instance);
814  return;
815  }
817  {
818  lpspiState->status = LPSPI_RECEIVE_FAIL;
819  (void)LPSPI_DRV_MasterAbortTransfer(instance);
821  return;
822  }
823 
824  /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */
825  if(LPSPI_HAL_GetStatusFlag(base,LPSPI_RX_DATA_FLAG) && (rxCount != (uint16_t)0))
826  {
827  LPSPI_DRV_ReadRXBuffer(instance);
828  }
829  /* Transmit data */
830  if (LPSPI_HAL_GetStatusFlag(base,LPSPI_TX_DATA_FLAG) && ((txCount != (uint16_t)0)))
831  {
832  LPSPI_DRV_FillupTxBuffer(instance);
833  }
834  txCount = lpspiState->txCount;
835  rxCount = lpspiState->rxCount;
836  if (txCount == (uint16_t)0)
837  {
838  /* Disable TX flag. Software buffer is empty.*/
841  /* Check if we're done with this transfer.*/
842  if (rxCount == (uint16_t)0)
843  {
845  {
847  }
848  }
849  }
850 }
851 
852 
853 /*******************************************************************************
854  * EOF
855  ******************************************************************************/
volatile uint16_t rxFrameCnt
#define LPSPI_INSTANCE_COUNT
Definition: S32K144.h:6194
volatile uint16_t txFrameCnt
Runtime state structure for the LPSPI master driver.
static void LPSPI_HAL_SetTxWatermarks(LPSPI_Type *base, uint32_t txWater)
Sets the TX FIFO watermark values.
Definition: lpspi_hal.h:433
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...
void LPSPI_HAL_GetFifoSizes(const LPSPI_Type *base, uint8_t *txFifoSize, uint8_t *rxFifoSize)
Gets the TX and RX FIFO sizes of the LPSPI module.
Definition: lpspi_hal.c:230
static const uint32_t s_baudratePrescaler[]
Definition: lpspi_hal.h:272
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
lpspi_signal_polarity_t pcsPolarity
static void LPSPI_HAL_ClearContCBit(LPSPI_Type *base)
Clear CONTC bit form TCR Register.
Definition: lpspi_hal.h:841
status_t LPSPI_DRV_MasterDeinit(uint32_t instance)
Shuts down a LPSPI instance.
Chip specific module features.
lpspi_transfer_type transferType
lpspi_transfer_type transferType
#define LPSPI_DMA_INSTANCE
lpspi_state_t * g_lpspiStatePtr[LPSPI_INSTANCE_COUNT]
void LPSPI_HAL_SetFlushFifoCmd(LPSPI_Type *base, bool flushTxFifo, bool flushRxFifo)
Flushes the LPSPI FIFOs.
Definition: lpspi_hal.c:250
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_HAL_SetDelay(LPSPI_Type *base, lpspi_delay_type_t whichDelay, uint32_t delay)
Manually configures a specific LPSPI delay parameter (module must be disabled to change the delay val...
Definition: lpspi_hal.c:620
void EDMA_HAL_TCDSetMajorCount(DMA_Type *base, uint32_t channel, uint32_t count)
Sets the major iteration count according to minor loop channel link setting.
Definition: edma_hal.c:388
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.
lpspi_prescaler_t
Prescaler values for LPSPI clock source. Implements : lpspi_prescaler_t_Class.
Definition: lpspi_hal.h:75
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.
status_t LPSPI_HAL_SetPinConfigMode(LPSPI_Type *base, lpspi_pin_config_t pinCfg, lpspi_data_out_config_t dataOutConfig, bool pcs3and2Enable)
Configures the LPSPI SDO/SDI pin configuration mode.
Definition: lpspi_hal.c:426
static void LPSPI_HAL_SetTxDmaCmd(LPSPI_Type *base, bool enable)
Sets the LPSPI Transmit Data DMA configuration (enable or disable).
Definition: lpspi_hal.h:533
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:78
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:125
status_t LPSPI_HAL_SetPcsPolarityMode(LPSPI_Type *base, lpspi_which_pcs_t whichPcs, lpspi_signal_polarity_t pcsPolarity)
Configures the desired LPSPI PCS polarity.
Definition: lpspi_hal.c:340
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:31
IRQn_Type g_lpspiIrqId[LPSPI_INSTANCE_COUNT]
Table to save LPSPI IRQ enumeration numbers defined in the CMSIS header file.
uint32_t LPSPI_HAL_SetBaudRate(LPSPI_Type *base, uint32_t bitsPerSec, uint32_t sourceClockInHz, uint32_t *tcrPrescaleValue)
Sets the LPSPI baud rate in bits per second.
Definition: lpspi_hal.c:472
static void LPSPI_HAL_Enable(LPSPI_Type *base)
Enables the LPSPI module.
Definition: lpspi_hal.h:340
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...
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_hal.h:132
static void LPSPI_HAL_SetRxDmaCmd(LPSPI_Type *base, bool enable)
Sets the LPSPI Receive Data DMA configuration (enable or disable).
Definition: lpspi_hal.h:545
static void LPSPI_HAL_SetIntMode(LPSPI_Type *base, lpspi_status_flag_t interruptSrc, bool enable)
Configures the LPSPI interrupts.
Definition: lpspi_hal.h:492
static lpspi_prescaler_t LPSPI_HAL_GetClockPrescaler(const LPSPI_Type *base)
Get the clock prescaler used for all LPSPI master logic.
Definition: lpspi_hal.h:881
static status_t LPSPI_DRV_MasterStartTransfer(uint32_t instance, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount)
static void EDMA_HAL_TCDSetDisableDmaRequestAfterTCDDoneCmd(DMA_Type *base, uint32_t channel, bool disable)
Disables/Enables the DMA request after the major loop completes for the TCD.
Definition: edma_hal.h:1117
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
void LPSPI_HAL_Init(LPSPI_Type *base)
Resets the LPSPI internal logic and registers to their default settings.
Definition: lpspi_hal.c:84
status_t EDMA_DRV_StartChannel(uint8_t channel)
Starts an eDMA channel.
Definition: edma_driver.c:765
status_t LPSPI_HAL_ClearStatusFlag(LPSPI_Type *base, lpspi_status_flag_t statusFlag)
Clears the LPSPI status flag.
Definition: lpspi_hal.c:278
static void LPSPI_HAL_SetRxWatermarks(LPSPI_Type *base, uint32_t rxWater)
Sets the RX FIFO watermark values.
Definition: lpspi_hal.h:416
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 Transmit Command Register configuration structure.
Definition: lpspi_hal.h:215
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
DMA_Type *const g_edmaBase[DMA_INSTANCE_COUNT]
Array for the eDMA module register base address.
Definition: edma_common.c:47
static void LPSPI_HAL_SetContCBit(LPSPI_Type *base)
Set CONTC bit form TCR Register.
Definition: lpspi_hal.h:854
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
__O uint32_t TDR
Definition: S32K144.h:6187
status_t LPSPI_DRV_MasterAbortTransfer(uint32_t instance)
Terminates an interrupt driven asynchronous transfer early.
lpspi_sck_polarity_t clkPolarity
LPSPI_Type * g_lpspiBase[LPSPI_INSTANCE_COUNT]
Table of base pointers for SPI instances.
#define MICROSECONDS
status_t EDMA_DRV_ConfigSingleBlockTransfer(uint8_t channel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t dataBufferSize)
Configures a simple single block data transfer with DMA.
Definition: edma_driver.c:487
const uint8_t * txBuff
void LPSPI_HAL_SetTxCommandReg(LPSPI_Type *base, const lpspi_tx_cmd_config_t *txCmdCfgSet)
Sets the Transmit Command Register (TCR) parameters.
Definition: lpspi_hal.c:663
__I uint32_t RDR
Definition: S32K144.h:6190
status_t LPSPI_HAL_Disable(LPSPI_Type *base)
Disables the LPSPI module.
Definition: lpspi_hal.c:183
status_t LPSPI_HAL_SetMasterSlaveMode(LPSPI_Type *base, lpspi_master_slave_mode_t mode)
Configures the LPSPI for master or slave.
Definition: lpspi_hal.c:208
status_t EDMA_DRV_InstallCallback(uint8_t channel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:285
semaphore_t lpspiSemaphore
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...
static bool LPSPI_HAL_GetStatusFlag(const LPSPI_Type *base, lpspi_status_flag_t statusFlag)
Gets the LPSPI status flag state.
Definition: lpspi_hal.h:459
transfer_status_t status