lpspi_slave_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 
82 #include <string.h>
83 #include "lpspi_slave_driver.h"
84 #include "clock_manager.h"
85 #include "interrupt_manager.h"
86 #include "lpspi_hw_access.h"
87 #include "device_registers.h"
88 
89 
90 /*******************************************************************************
91  * Definitions
92  ******************************************************************************/
93 
94 /* Callback for DMA transfer done.*/
95 static void LPSPI_DRV_SlaveCompleteDMATransfer(void* parameter, edma_chn_status_t status);
96 
97 /*******************************************************************************
98  * Code
99  ******************************************************************************/
100  /*
101  * Implements : LPSPI_DRV_SlaveInit_Activity
102  */
103 status_t LPSPI_DRV_SlaveInit(uint32_t instance,
104  lpspi_state_t * lpspiState,
105  const lpspi_slave_config_t * slaveConfig)
106 {
107  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
108  DEV_ASSERT(lpspiState != NULL);
109  DEV_ASSERT(slaveConfig != NULL);
110  DEV_ASSERT(!((slaveConfig->bitcount > 32U) && (slaveConfig->lsbFirst == false)));
111  LPSPI_Type * base = g_lpspiBase[instance];
112  status_t errorCode = STATUS_SUCCESS;
113 
114  lpspiState->lsb = slaveConfig->lsbFirst;
115  lpspiState->bitsPerFrame = slaveConfig->bitcount;
116  lpspiState->transferType = slaveConfig->transferType;
117  lpspiState->isBlocking = false;
118  /* Store DMA channels numbers used for DMA transfer */
119  lpspiState->rxDMAChannel = slaveConfig->rxDMAChannel;
120  lpspiState->txDMAChannel = slaveConfig->txDMAChannel;
121  /* Store callback */
122  lpspiState->callback = slaveConfig->callback;
123  lpspiState->callbackParam = slaveConfig->callbackParam;
124  /* Calculate the bytes/frame for lpspiState->bytesPerFrame. */
125  lpspiState->bytesPerFrame = (uint16_t)((lpspiState->bitsPerFrame + 7U) / 8U);
126  /* Due to DMA limitations frames of 3 bytes/frame will be internally handled as 4 bytes/frame. */
127  if (lpspiState->bytesPerFrame == 3U)
128  {
129  lpspiState->bytesPerFrame = 4U;
130  }
131  /* Due to some limitations all frames bigger than 4 bytes/frame must be composed only from 4 bytes chunks. */
132  if (lpspiState->bytesPerFrame > 4U)
133  {
134  lpspiState->bytesPerFrame = (((lpspiState->bytesPerFrame - 1U) / 4U) + 1U) * 4U;
135  }
136  lpspiState->isTransferInProgress = false;
137  /* Initialize the semaphore */
138  errorCode = OSIF_SemaCreate(&(lpspiState->lpspiSemaphore), 0);
139  DEV_ASSERT(errorCode == STATUS_SUCCESS);
140  g_lpspiStatePtr[instance] = lpspiState;
141 
142  /* Configure registers */
143  LPSPI_Init(base);
144 
145  /* Configure lpspi to slave mode */
146  (void)LPSPI_SetMasterSlaveMode(base, LPSPI_SLAVE);
147  /* Set Pin settings */
148  (void)LPSPI_SetPinConfigMode(base, LPSPI_SDI_IN_SDO_OUT, LPSPI_DATA_OUT_RETAINED, true);
149  /* Calculate the FIFO size for the LPSPI */
150  LPSPI_GetFifoSizes(base, &(lpspiState->fifoSize), NULL);
151 
152  /* Set polarity */
153  (void)LPSPI_SetPcsPolarityMode(base, slaveConfig->whichPcs, slaveConfig->pcsPolarity);
154 
155  /* Write the TCR for this transfer */
156  lpspi_tx_cmd_config_t txCmdCfg = {
157  .frameSize = lpspiState->bitsPerFrame,
158  .width = LPSPI_SINGLE_BIT_XFER,
159  .txMask = false,
160  .rxMask = false,
161  .byteSwap = false,
162  .lsbFirst = slaveConfig->lsbFirst,
163  .clkPhase = slaveConfig->clkPhase,
164  .clkPolarity = slaveConfig->clkPolarity,
165  .whichPcs = slaveConfig->whichPcs
166  };
167 
168  /* Write to the TX CMD register */
169  LPSPI_SetTxCommandReg(base, &txCmdCfg);
170  LPSPI_Enable(base);
171  /* Enable the interrupt source */
172  INT_SYS_EnableIRQ(g_lpspiIrqId[instance]);
173 
174  return errorCode;
175 }
176 
177  /*
178  * Implements : LPSPI_DRV_SlaveDeinit_Activity
179  */
180 status_t LPSPI_DRV_SlaveDeinit(uint32_t instance)
181 {
182  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
183  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
184  /* Instantiate local variable of type lpspi_master_state_t and point to global state */
185  const lpspi_state_t * lpspiState = (lpspi_state_t *)g_lpspiStatePtr[instance];
186  LPSPI_Type *base = g_lpspiBase[instance];
187  status_t errorCode = STATUS_SUCCESS;
188 
189  /* Check if a transfer is still in progress */
190  DEV_ASSERT(lpspiState->isTransferInProgress == false);
191  /* Destroy the semaphore */
192  errorCode = OSIF_SemaDestroy(&(lpspiState->lpspiSemaphore));
193  DEV_ASSERT(errorCode == STATUS_SUCCESS);
194  /* Reset the LPSPI registers to their default state, including disabling the LPSPI */
195  LPSPI_Init(base);
196 
197  /* Disable the interrupt*/
198  INT_SYS_DisableIRQ(g_lpspiIrqId[instance]);
199 
200  /* Clear the state pointer. */
201  g_lpspiStatePtr[instance] = NULL;
202 
203  return errorCode;
204 }
205 
206  /*
207  * Implements : LPSPI_DRV_SlaveTransferBlocking_Activity
208  */
210  const uint8_t *sendBuffer,
211  uint8_t *receiveBuffer,
212  uint16_t transferByteCount,
213  uint32_t timeout)
214 {
215  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
216  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
217  lpspi_state_t * state = (lpspi_state_t *)g_lpspiStatePtr[instance];
218  status_t error;
219  status_t osifError;
220  state->isBlocking = true;
221  error = LPSPI_DRV_SlaveTransfer(instance, sendBuffer, receiveBuffer, transferByteCount);
222  if(error != STATUS_SUCCESS)
223  {
225  return error;
226  }
227 
228  /* As this is a synchronous transfer, wait until the transfer is complete.*/
229  osifError = OSIF_SemaWait(&(state->lpspiSemaphore), timeout);
230 
231  if (osifError == STATUS_TIMEOUT)
232  {
233  /* Set isBlocking variable to false to avoid dummy semaphore post. */
234  state->isBlocking = false;
235  /* Complete transfer. */
236  (void)LPSPI_DRV_SlaveAbortTransfer(instance);
237  return(STATUS_TIMEOUT);
238  }
239 
241 
242  return STATUS_SUCCESS;
243 }
244 
245  /*
246  * Implements : LPSPI_DRV_SlaveTransfer_Activity
247  */
249  const uint8_t *sendBuffer,
250  uint8_t *receiveBuffer,
251  uint16_t transferByteCount)
252 {
253  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
254  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
255  DEV_ASSERT(!((sendBuffer == NULL) && (receiveBuffer == NULL)));
256  LPSPI_Type * base = g_lpspiBase[instance];
257  lpspi_state_t * state = (lpspi_state_t *)g_lpspiStatePtr[instance];
259  /* The number of transferred bytes should be divisible by frame size */
260  if ((uint16_t)(transferByteCount % state->bytesPerFrame) != (uint16_t)0)
261  {
262  return STATUS_ERROR;
263  }
264  /* Check if LPSPI module isn't busy */
265  if (state->isTransferInProgress == true)
266  {
267  return STATUS_BUSY;
268  }
269  /* Initialize the status of the current transfer */
270  state->status = LPSPI_TRANSFER_OK;
271  /* Clean RX and TX buffers */
272  LPSPI_SetFlushFifoCmd(base, true, true);
273  /* The second flush command is used to avoid the case when one word is still in shifter. */
274  LPSPI_SetFlushFifoCmd(base, true, true);
275  /* Clear all interrupts sources */
276  (void)LPSPI_ClearStatusFlag(base, LPSPI_ALL_STATUS);
277  /* Enable fault interrupts sources */
278  LPSPI_SetIntMode(base,LPSPI_TRANSMIT_ERROR , true);
279  LPSPI_SetIntMode(base,LPSPI_RECEIVE_ERROR , true);
280  /* Fill out the other members of the run-time state structure. */
281  state->txBuff = (const uint8_t *)sendBuffer;
282  state->rxBuff = (uint8_t *)receiveBuffer;
283  if (state->transferType == LPSPI_USING_INTERRUPTS)
284  {
285  state->txCount = transferByteCount;
286  state->rxCount = transferByteCount;
287  state->txFrameCnt = 0;
288  state->rxFrameCnt = 0;
289  state->isPcsContinuous = false;
290  /* Configure watermarks */
291  LPSPI_SetRxWatermarks(base, 0U);
292  LPSPI_SetTxWatermarks(base, 2U);
293 
294  state->isTransferInProgress = true;
295  /* Enable interrupts for RX and TX only if it's necessary */
296  if(state->txBuff != NULL)
297  {
298  LPSPI_SetIntMode(base,LPSPI_TX_DATA_FLAG , true);
299  }
300  else
301  {
302  state->txCount = 0;
303  }
304  if(state->rxBuff != NULL)
305  {
306  LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, true);
307  }
308  else
309  {
310  state->rxCount = 0;
311  }
312  }
313  else
314  {
315  /* Configure watermarks */
316  LPSPI_SetRxWatermarks(base, 0U);
317  LPSPI_SetTxWatermarks(base, 3U);
318  /* When LPSPI use DMA frames with 3 bytes size are not accepted. */
319  switch(state->bytesPerFrame)
320  {
321  case 1: dmaTransferSize = EDMA_TRANSFER_SIZE_1B; break;
322  case 2: dmaTransferSize = EDMA_TRANSFER_SIZE_2B; break;
323  case 4: dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
324  default: dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
325  }
326  if(receiveBuffer != NULL)
327  {
329  (uint32_t)(&(base->RDR)),(uint32_t)receiveBuffer, dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
330  (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
331 
332  state->rxCount = transferByteCount;
333  /* Start RX channel */
334  (void)EDMA_DRV_StartChannel(state->rxDMAChannel);
335  }
336  else
337  {
338  state->rxCount = 0;
339  }
340  if(sendBuffer != NULL)
341  {
343  (uint32_t)sendBuffer, (uint32_t)(&(base->TDR)), dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
344  (uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
345 
346  state->txCount = transferByteCount;
347  /* Start TX channel */
348  (void)EDMA_DRV_StartChannel(state->txDMAChannel);
349  }
350  else
351  {
352  state->txCount = 0;
353  }
354  /* Configure which channel will generate transfer complete */
355  /* If current transfer uses both buffers (RX and TX) RX transfer done will generate transfer complete
356  * interrupt. Otherwise transfer complete will be generate by available channel(RX or TX).
357  */
358  if(receiveBuffer != NULL)
359  {
361  }
362  else
363  {
365  }
366  state->isTransferInProgress = true;
367  /* Enable LPSPI DMA request */
368  if (receiveBuffer != NULL)
369  {
370  LPSPI_SetRxDmaCmd(base, true);
371  }
372  if (sendBuffer != NULL)
373  {
374  LPSPI_SetTxDmaCmd(base, true);
375  }
376  }
377  return STATUS_SUCCESS;
378 }
379 
380 void LPSPI_DRV_SlaveIRQHandler(uint32_t instance)
381 {
382  LPSPI_Type * base = g_lpspiBase[instance];
383  lpspi_state_t * lpspiState = (lpspi_state_t *)g_lpspiStatePtr[instance];
384  uint16_t txCount, rxCount;
385 
386  /* If an error is detected the transfer will be aborted */
387  if ((bool)LPSPI_GetStatusFlag(base, LPSPI_TRANSMIT_ERROR) && (lpspiState->txBuff != NULL))
388  {
389  lpspiState->status = LPSPI_TRANSMIT_FAIL;
390  (void)LPSPI_DRV_SlaveAbortTransfer(instance);
391  return;
392  }
393  if (LPSPI_GetStatusFlag(base, LPSPI_RECEIVE_ERROR) && (lpspiState->rxBuff != NULL))
394  {
395  lpspiState->status = LPSPI_RECEIVE_FAIL;
396  (void)LPSPI_DRV_SlaveAbortTransfer(instance);
397  return;
398  }
399 
400  /* Receive data */
401  if(LPSPI_GetStatusFlag(base,LPSPI_RX_DATA_FLAG))
402  {
403  LPSPI_DRV_ReadRXBuffer(instance);
404  }
405  /* Transmit data */
406  txCount = lpspiState->txCount;
407  if (LPSPI_GetStatusFlag(base,LPSPI_TX_DATA_FLAG) && ((txCount != (uint8_t)0)))
408  {
409  LPSPI_DRV_FillupTxBuffer(instance);
410  }
411  txCount = lpspiState->txCount;
412  rxCount = lpspiState->rxCount;
413  /* If all bytes are sent disable interrupt TDF */
414  if (txCount == (uint8_t)0)
415  {
416  LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, false);
417  }
418  /* If all bytes are received disable interrupt RDF */
419  if (rxCount == (uint8_t)0)
420  {
421  LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, false);
422  }
423  if ((rxCount == (uint8_t)0) && (txCount == (uint8_t)0))
424  {
425  /* Disable fault interrupts sources */
426  LPSPI_SetIntMode(base,LPSPI_TRANSMIT_ERROR , false);
427  LPSPI_SetIntMode(base,LPSPI_RECEIVE_ERROR , false);
428 
429  /* Call the callback if it is defined */
430  if (lpspiState->callback != NULL)
431  {
432  lpspiState->callback(lpspiState, SPI_EVENT_END_TRANSFER, lpspiState->callbackParam);
433  }
434 
435  /* If the transfer is blocking post the semaphore */
436  if(lpspiState->isBlocking == true)
437  {
438  (void)OSIF_SemaPost(&(lpspiState->lpspiSemaphore));
439  lpspiState->isBlocking = false;
440  }
441 
442  /* Update internal state of the transfer */
443  lpspiState->isTransferInProgress = false;
444  }
445 }
446 
447  /*
448  * Implements : LPSPI_DRV_SlaveAbortTransfer_Activity
449  */
451 {
452  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
453  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
454  LPSPI_Type * base = g_lpspiBase[instance];
455  lpspi_state_t * state = (lpspi_state_t *)g_lpspiStatePtr[instance];
456 
457  if (state->transferType == LPSPI_USING_INTERRUPTS)
458  {
459  /* Disable interrupts */
460  LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, false);
461  LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, false);
462  }
463  else
464  {
465  /* Disable LPSPI DMA request */
466  LPSPI_SetRxDmaCmd(base, false);
467  LPSPI_SetTxDmaCmd(base, false);
468  }
469 
471 
472  state->isTransferInProgress = false;
473  /* Clean RX and TX buffers */
474  LPSPI_SetFlushFifoCmd(base, true, true);
475  /* The second flush command is used to avoid the case when one word is still in shifter. */
476  LPSPI_SetFlushFifoCmd(base, true, true);
477  if(state->isBlocking == true)
478  {
479  (void)OSIF_SemaPost(&(state->lpspiSemaphore));
480  state->isBlocking = false;
481  }
482  return STATUS_SUCCESS;
483 }
484 
485  /*
486  * Implements : LPSPI_DRV_SlaveGetTransferStatus_Activity
487  */
488 status_t LPSPI_DRV_SlaveGetTransferStatus(uint32_t instance,uint32_t * bytesRemained)
489 {
490  DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
491  DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
492  const lpspi_state_t * lpspiState = (lpspi_state_t *)g_lpspiStatePtr[instance];
493 
494  /* Fill in the bytes transferred.*/
495  if (bytesRemained != NULL)
496  {
497  *bytesRemained = lpspiState->txCount;
498  }
499  if (lpspiState->status == LPSPI_TRANSFER_OK)
500  {
501  return (status_t)(lpspiState->isTransferInProgress ? STATUS_BUSY : STATUS_SUCCESS);
502  }
503  else
504  {
505  return STATUS_ERROR;
506  }
507 }
508 
513 static void LPSPI_DRV_SlaveCompleteDMATransfer(void* parameter, edma_chn_status_t status)
514 {
515  uint32_t instance = (uint32_t)parameter;
516  lpspi_state_t * lpspiState = (lpspi_state_t *)g_lpspiStatePtr[instance];
517 
518  (void)status;
519  (void)LPSPI_DRV_SlaveAbortTransfer(instance);
520  if (lpspiState->callback != NULL)
521  {
522  lpspiState->callback(lpspiState, SPI_EVENT_END_TRANSFER, lpspiState->callbackParam);
523  }
524 }
volatile uint16_t rxFrameCnt
#define LPSPI_INSTANCE_COUNT
Definition: S32K118.h:6049
volatile uint16_t txFrameCnt
Runtime state structure for the LPSPI master driver.
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.
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
LPSPI_Type * g_lpspiBase[(2u)]
Table of base pointers for SPI instances.
lpspi_transfer_type transferType
lpspi_signal_polarity_t pcsPolarity
spi_callback_t callback
lpspi_which_pcs_t whichPcs
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
void LPSPI_DRV_FillupTxBuffer(uint32_t instance)
The function LPSPI_DRV_FillupTxBuffer writes data in TX hardware buffer depending on driver state and...
status_t LPSPI_DRV_SlaveTransfer(uint32_t instance, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount)
Starts the transfer data on LPSPI bus using a non-blocking call.
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
lpspi_clock_phase_t clkPhase
#define DEV_ASSERT(x)
Definition: devassert.h:77
volatile uint16_t rxCount
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:255
status_t LPSPI_DRV_SlaveTransferBlocking(uint32_t instance, const uint8_t *sendBuffer, uint8_t *receiveBuffer, uint16_t transferByteCount, uint32_t timeout)
Transfers data on LPSPI bus using a blocking call.
edma_transfer_size_t
eDMA transfer configuration Implements : edma_transfer_size_t_Class
Definition: edma_driver.h:200
volatile uint16_t txCount
lpspi_sck_polarity_t clkPolarity
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
status_t LPSPI_DRV_SlaveInit(uint32_t instance, lpspi_state_t *lpspiState, const lpspi_slave_config_t *slaveConfig)
Initializes a LPSPI instance for a slave mode operation, using interrupt mechanism.
User configuration structure for the SPI slave driver. Implements : lpspi_slave_config_t_Class.
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 void LPSPI_DRV_SlaveCompleteDMATransfer(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...
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
volatile bool isTransferInProgress
status_t LPSPI_DRV_SlaveAbortTransfer(uint32_t instance)
Aborts the transfer that started by a non-blocking call transfer function.
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
lpspi_transfer_type transferType
status_t LPSPI_DRV_SlaveGetTransferStatus(uint32_t instance, uint32_t *bytesRemained)
Returns whether the previous transfer is finished.
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
status_t LPSPI_DRV_SlaveDeinit(uint32_t instance)
Shuts down an LPSPI instance interrupt mechanism.
const uint8_t * txBuff
void LPSPI_DRV_SlaveIRQHandler(uint32_t instance)
Interrupt handler for LPSPI slave mode. This handler uses the buffers stored in the lpspi_master_stat...
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.
transfer_status_t status