flexio_i2c_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
19 #include "flexio_i2c_driver.h"
20 #include "flexio_hw_access.h"
21 #include "flexio_common.h"
22 #include "clock_manager.h"
23 
98 /*******************************************************************************
99  * Variables
100  ******************************************************************************/
101 
104  /* Constraints used for baud rate computation */
105 #define DIVIDER_MIN_VALUE 1U
106 #define DIVIDER_MAX_VALUE 0xFFU
107 
108  /* Shifters/Timers used for I2C simulation The parameter x represents the
109  resourceIndex value for the current driver instance */
110 #define TX_SHIFTER(x) (x)
111 #define RX_SHIFTER(x) (uint8_t)((x) + 1U)
112 #define SCL_TIMER(x) (x)
113 #define CONTROL_TIMER(x) (uint8_t)((x) + 1U)
114 
115 /*******************************************************************************
116  * Private Functions
117  ******************************************************************************/
118 
119 
120 /*FUNCTION**********************************************************************
121  *
122  * Function Name : FLEXIO_I2C_DRV_MasterComputeBaudRateDivider
123  * Description : Computes the baud rate divider for a target baud rate
124  *
125  *END**************************************************************************/
126 static void FLEXIO_I2C_DRV_MasterComputeBaudRateDivider(uint32_t baudRate,
127  uint16_t *divider,
128  uint32_t inputClock)
129 {
130  uint32_t tmpDiv;
131 
132  /* Compute divider: ((input_clock / baud_rate) / 2) - 1 - 1. The extra -1 is from the
133  timer reset setting used for clock stretching. Round to nearest integer */
134  tmpDiv = ((inputClock + baudRate) / (2U * baudRate)) - 2U;
135  /* Enforce upper/lower limits */
136  if (tmpDiv < DIVIDER_MIN_VALUE)
137  {
138  tmpDiv = DIVIDER_MIN_VALUE;
139  }
140  if (tmpDiv > DIVIDER_MAX_VALUE)
141  {
142  tmpDiv = DIVIDER_MAX_VALUE;
143  }
144 
145  *divider = (uint16_t)tmpDiv;
146 }
147 
148 
149 /*FUNCTION**********************************************************************
150  *
151  * Function Name : FLEXIO_I2C_DRV_MasterConfigure
152  * Description : configures the FLEXIO module as I2C master
153  *
154  *END**************************************************************************/
155 static void FLEXIO_I2C_DRV_MasterConfigure(const flexio_i2c_master_state_t *master, uint32_t inputClock, uint32_t baudRate)
156 {
157  FLEXIO_Type *baseAddr;
158  uint16_t divider;
159  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
160 
161  baseAddr = g_flexioBase[master->flexioCommon.instance];
162  resourceIndex = master->flexioCommon.resourceIndex;
163 
164  /* Compute divider.*/
165  FLEXIO_I2C_DRV_MasterComputeBaudRateDivider(baudRate, &divider, inputClock);
166 
167  /* Configure tx shifter */
168  FLEXIO_SetShifterConfig(baseAddr,
169  TX_SHIFTER(resourceIndex),
170  FLEXIO_SHIFTER_START_BIT_0,
171  FLEXIO_SHIFTER_STOP_BIT_1,
172  FLEXIO_SHIFTER_SOURCE_PIN);
173  /* Shifter disabled and pin enabled causes the pin to be held low.
174  So disable pin too, will be enabled at transfer time. */
175  FLEXIO_SetShifterControl(baseAddr,
176  TX_SHIFTER(resourceIndex),
177  FLEXIO_SHIFTER_MODE_DISABLED,
178  master->sdaPin, /* output on SDA pin */
179  FLEXIO_PIN_POLARITY_LOW,
180  FLEXIO_PIN_CONFIG_DISABLED,
181  CONTROL_TIMER(resourceIndex), /* use control timer to drive the shifter */
182  FLEXIO_TIMER_POLARITY_POSEDGE);
183 
184  /* Configure rx shifter */
185  FLEXIO_SetShifterConfig(baseAddr,
186  RX_SHIFTER(resourceIndex),
187  FLEXIO_SHIFTER_START_BIT_DISABLED,
188  FLEXIO_SHIFTER_STOP_BIT_0,
189  FLEXIO_SHIFTER_SOURCE_PIN);
190  FLEXIO_SetShifterControl(baseAddr,
191  RX_SHIFTER(resourceIndex),
192  FLEXIO_SHIFTER_MODE_DISABLED,
193  master->sdaPin, /* input from SDA pin */
194  FLEXIO_PIN_POLARITY_HIGH,
195  FLEXIO_PIN_CONFIG_DISABLED,
196  CONTROL_TIMER(resourceIndex), /* use control timer to drive the shifter */
197  FLEXIO_TIMER_POLARITY_NEGEDGE);
198 
199  /* Configure SCL timer */
200  FLEXIO_SetTimerCompare(baseAddr, SCL_TIMER(resourceIndex), divider);
201  FLEXIO_SetTimerConfig(baseAddr,
202  SCL_TIMER(resourceIndex),
203  FLEXIO_TIMER_START_BIT_ENABLED,
204  FLEXIO_TIMER_STOP_BIT_TIM_DIS,
205  FLEXIO_TIMER_ENABLE_TRG_HIGH, /* enable when Tx data is available */
206  FLEXIO_TIMER_DISABLE_TIM_CMP,
207  FLEXIO_TIMER_RESET_PIN_OUT, /* reset if output equals pin (for clock stretching) */
208  FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR, /* decrement on FlexIO clock */
209  FLEXIO_TIMER_INITOUT_ZERO);
210  FLEXIO_SetTimerControl(baseAddr,
211  SCL_TIMER(resourceIndex),
212  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
213  FLEXIO_TRIGGER_POLARITY_LOW,
214  FLEXIO_TRIGGER_SOURCE_INTERNAL,
215  master->sclPin, /* output on SCL pin */
216  FLEXIO_PIN_POLARITY_HIGH,
217  FLEXIO_PIN_CONFIG_OPEN_DRAIN, /* enable output */
218  FLEXIO_TIMER_MODE_DISABLED);
219 
220  /* Configure control timer for shifters */
221  FLEXIO_SetTimerCompare(baseAddr, CONTROL_TIMER(resourceIndex), 0x000FU);
222  FLEXIO_SetTimerConfig(baseAddr,
223  CONTROL_TIMER(resourceIndex),
224  FLEXIO_TIMER_START_BIT_ENABLED,
225  FLEXIO_TIMER_STOP_BIT_TIM_CMP,
226  FLEXIO_TIMER_ENABLE_TIM_ENABLE, /* enable on SCL timer enable */
227  FLEXIO_TIMER_DISABLE_TIM_DISABLE, /* disable on SCL timer disable */
228  FLEXIO_TIMER_RESET_NEVER,
229  FLEXIO_TIMER_DECREMENT_PIN_SHIFT_PIN, /* decrement on SCL pin input */
230  FLEXIO_TIMER_INITOUT_ONE);
231  FLEXIO_SetTimerControl(baseAddr,
232  CONTROL_TIMER(resourceIndex),
233  (uint8_t)((TX_SHIFTER(resourceIndex) << 2U) + 1U), /* trigger on tx shifter status flag */
234  FLEXIO_TRIGGER_POLARITY_LOW,
235  FLEXIO_TRIGGER_SOURCE_INTERNAL,
236  master->sclPin, /* use SCL pin as input */
237  FLEXIO_PIN_POLARITY_LOW,
238  FLEXIO_PIN_CONFIG_DISABLED,
239  FLEXIO_TIMER_MODE_DISABLED);
240 }
241 
242 
243 /*FUNCTION**********************************************************************
244  *
245  * Function Name : FLEXIO_I2C_DRV_MasterSetBytesNo
246  * Description : configures the number of SCL clocks needed for the entire transmission
247  *
248  *END**************************************************************************/
249 static void FLEXIO_I2C_DRV_MasterSetBytesNo(FLEXIO_Type *baseAddr, const flexio_i2c_master_state_t *master)
250 {
251  uint16_t timerCmp;
252  uint32_t bytesNo;
253  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
254 
255  resourceIndex = master->flexioCommon.resourceIndex;
256  /* Compute number of SCL ticks, including address */
257  bytesNo = master->txRemainingBytes;
258  bytesNo = (bytesNo * 18U) + 1U;
259  /* Set number of ticks in low part of timer compare register */
260  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCL_TIMER(resourceIndex));
261  timerCmp = (uint16_t)((timerCmp & 0x00FFU) | (uint16_t)((bytesNo & 0xFFU) << 8U));
262  FLEXIO_SetTimerCompare(baseAddr, SCL_TIMER(resourceIndex), timerCmp);
263 }
264 
265 
266 /*FUNCTION**********************************************************************
267  *
268  * Function Name : FLEXIO_I2C_DRV_MasterSendAddress
269  * Description : send address byte
270  *
271  *END**************************************************************************/
272 static void FLEXIO_I2C_DRV_MasterSendAddress(FLEXIO_Type *baseAddr, const flexio_i2c_master_state_t *master)
273 {
274  uint8_t addrByte;
275  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
276 
277  resourceIndex = master->flexioCommon.resourceIndex;
278  /* Address byte: slave 7-bit address + D = 0(transmit) or 1 (receive) */
279  addrByte = (uint8_t)((uint8_t)(master->slaveAddress << 1U) + (uint8_t)(master->receive ? 1U : 0U));
280  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), (uint32_t)addrByte << 24U, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
281 }
282 
283 
284 /*FUNCTION**********************************************************************
285  *
286  * Function Name : FLEXIO_I2C_DRV_ReadData
287  * Description : Handles data reception
288  *
289  *END**************************************************************************/
290 static void FLEXIO_I2C_DRV_ReadData(flexio_i2c_master_state_t *master)
291 {
292  FLEXIO_Type *baseAddr;
293  uint8_t data;
294  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
295 
296  baseAddr = g_flexioBase[master->flexioCommon.instance];
297  resourceIndex = master->flexioCommon.resourceIndex;
298 
299  /* Read data from rx shifter */
300  data = (uint8_t)FLEXIO_ReadShifterBuffer(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
301 
302  if (master->rxRemainingBytes == 0U)
303  {
304  return;
305  }
306 
307  if (master->addrReceived == false)
308  {
309  /* This was the address byte */
310  master->addrReceived = true;
311  if (master->receive == true)
312  {
313  /* Send ACK from now on */
314  FLEXIO_SetShifterStopBit(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_STOP_BIT_0);
315  }
316  }
317  else
318  {
319  master->rxRemainingBytes--;
320  if (master->receive == true)
321  {
322  /* Put data in user buffer */
323  *(master->data) = data;
324  master->data++;
325  }
326  }
327  if ((master->receive == true) && (master->rxRemainingBytes == 1U))
328  {
329  /* Send NACK for last byte */
330  FLEXIO_SetShifterStopBit(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_STOP_BIT_1);
331  /* Also instruct rx shifter to expect NACK */
332  FLEXIO_SetShifterStopBit(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_STOP_BIT_1);
333  }
334 }
335 
336 
337 /*FUNCTION**********************************************************************
338  *
339  * Function Name : FLEXIO_I2C_DRV_WriteData
340  * Description : Handles data transmission
341  *
342  *END**************************************************************************/
343 static void FLEXIO_I2C_DRV_WriteData(flexio_i2c_master_state_t *master)
344 {
345  FLEXIO_Type *baseAddr;
346  uint32_t data;
347  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
348 
349  baseAddr = g_flexioBase[master->flexioCommon.instance];
350  resourceIndex = master->flexioCommon.resourceIndex;
351 
352  /* If txRemainingBytes == 0 the transmission is over */
353  if (master->txRemainingBytes == 0U)
354  {
355  return;
356  }
357 
358  master->txRemainingBytes--;
359 
360  if (master->txRemainingBytes == 0U)
361  {
362  /* Done transmitting */
363  if (master->sendStop == true)
364  {
365  /* Transmit stop condition */
366  data = 0x0;
367  }
368  else
369  {
370  /* Do not transmit stop condition */
371  data = 0xFFU;
372  }
373  }
374  else if (master->receive == true)
375  {
376  /* Transmit 0xFF to leave the line free while receiving */
377  data = 0xFFU;
378  }
379  else
380  {
381  /* Read data from user buffer */
382  data = *(master->data);
383  master->data++;
384  }
385 
386  /* Shift data before bit-swapping it to get the relevant bits in the lower part of the shifter */
387  data <<= 24U;
388  FLEXIO_WriteShifterBuffer(baseAddr, TX_SHIFTER(resourceIndex), data, FLEXIO_SHIFTER_RW_MODE_BIT_SWAP);
389 }
390 
391 
392 /*FUNCTION**********************************************************************
393  *
394  * Function Name : FLEXIO_I2C_DRV_MasterEndTransfer
395  * Description : End the current transfer
396  *
397  *END**************************************************************************/
398 static void FLEXIO_I2C_DRV_MasterEndTransfer(flexio_i2c_master_state_t *master)
399 {
400  FLEXIO_Type *baseAddr;
401  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
402 
403  baseAddr = g_flexioBase[master->flexioCommon.instance];
404  resourceIndex = master->flexioCommon.resourceIndex;
405 
406  /* Restore Rx stop bit, in case it was changed by a receive */
407  FLEXIO_SetShifterStopBit(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_STOP_BIT_0);
408  /* Restore Tx stop bit, in case it was changed by a receive */
409  FLEXIO_SetShifterStopBit(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_STOP_BIT_1);
410  /* Clear Rx status in case there is a character left in the buffer */
411  FLEXIO_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
412 
413  /* Disable transfer engine */
414  switch (master->driverType)
415  {
417  /* Disable interrupts for Rx and Tx shifters */
418  FLEXIO_SetShifterInterrupt(baseAddr,
419  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
420  false);
421  FLEXIO_SetShifterErrorInterrupt(baseAddr,
422  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
423  false);
424  /* Disable interrupt for SCL timer */
425  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << SCL_TIMER(resourceIndex)), false);
426  break;
428  /* Nothing to do here */
429  break;
431  /* Disable error interrupt for Rx shifter */
432  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), false);
433  /* Disable interrupt for SCL timer */
434  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << SCL_TIMER(resourceIndex)), false);
435  /* Stop DMA channels */
436  (void)EDMA_DRV_StopChannel(master->txDMAChannel);
437  (void)EDMA_DRV_StopChannel(master->rxDMAChannel);
438  /* Disable FlexIO DMA requests for both shifters */
439  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))), false);
440  break;
441  default:
442  /* Impossible type - do nothing */
443  break;
444  }
445 
446  master->driverIdle = true;
447 
448  /* Signal transfer end for blocking transfers */
449  if (master->blocking == true)
450  {
451  (void)OSIF_SemaPost(&(master->idleSemaphore));
452  }
453 }
454 
455 
456 /*FUNCTION**********************************************************************
457  *
458  * Function Name : FLEXIO_I2C_DRV_MasterEnableTransfer
459  * Description : Enables timers and shifters to start a transfer
460  *
461  *END**************************************************************************/
462 static void FLEXIO_I2C_DRV_MasterEnableTransfer(flexio_i2c_master_state_t *master)
463 {
464  FLEXIO_Type *baseAddr;
465  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
466 
467  resourceIndex = master->flexioCommon.resourceIndex;
468  baseAddr = g_flexioBase[master->flexioCommon.instance];
469 
470  /* enable timers and shifters */
471  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_TRANSMIT);
472  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_RECEIVE);
473  FLEXIO_SetTimerMode(baseAddr, SCL_TIMER(resourceIndex), FLEXIO_TIMER_MODE_8BIT_BAUD);
474  FLEXIO_SetTimerMode(baseAddr, CONTROL_TIMER(resourceIndex), FLEXIO_TIMER_MODE_16BIT);
475  /* enable Tx pin */
476  FLEXIO_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_OPEN_DRAIN);
477 }
478 
479 
480 /*FUNCTION**********************************************************************
481  *
482  * Function Name : FLEXIO_I2C_DRV_MasterStopTransfer
483  * Description : Forcefully stops the current transfer
484  *
485  *END**************************************************************************/
486 static void FLEXIO_I2C_DRV_MasterStopTransfer(flexio_i2c_master_state_t *master)
487 {
488  FLEXIO_Type *baseAddr;
489  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
490 
491  resourceIndex = master->flexioCommon.resourceIndex;
492  baseAddr = g_flexioBase[master->flexioCommon.instance];
493 
494  /* disable Tx pin */
495  FLEXIO_SetShifterPinConfig(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_PIN_CONFIG_DISABLED);
496  /* disable and re-enable timers and shifters to reset them */
497  FLEXIO_SetShifterMode(baseAddr, TX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
498  FLEXIO_SetShifterMode(baseAddr, RX_SHIFTER(resourceIndex), FLEXIO_SHIFTER_MODE_DISABLED);
499  FLEXIO_SetTimerMode(baseAddr, SCL_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
500  FLEXIO_SetTimerMode(baseAddr, CONTROL_TIMER(resourceIndex), FLEXIO_TIMER_MODE_DISABLED);
501 
502  /* clear any leftover error flags */
503  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
504  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
505  /* discard any leftover rx. data */
506  FLEXIO_ClearShifterStatus(baseAddr, RX_SHIFTER(resourceIndex));
507 
508  /* end the transfer */
509  FLEXIO_I2C_DRV_MasterEndTransfer(master);
510 }
511 
512 
513 /*FUNCTION**********************************************************************
514  *
515  * Function Name : FLEXIO_I2C_DRV_MasterWaitTransferEnd
516  * Description : waits for the end of a blocking transfer
517  *
518  *END**************************************************************************/
519 static status_t FLEXIO_I2C_DRV_MasterWaitTransferEnd(flexio_i2c_master_state_t *master, uint32_t timeout)
520 {
521  status_t osifError = STATUS_SUCCESS;
522 
523  switch (master->driverType)
524  {
526  /* Wait for transfer to be completed by the IRQ */
527  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
528  break;
530  /* Call FLEXIO_I2C_DRV_MasterGetStatus() to do the transfer */
531  while (FLEXIO_I2C_DRV_MasterGetStatus(master, NULL) == STATUS_BUSY)
532  {
533  }
534  break;
536  /* Wait for transfer to be completed by the DMA IRQ */
537  osifError = OSIF_SemaWait(&(master->idleSemaphore), timeout);
538  break;
539  default:
540  /* Impossible type - do nothing */
541  break;
542  }
543 
544  /* blocking transfer is over */
545  master->blocking = false;
546  if (osifError == STATUS_TIMEOUT)
547  {
548  /* abort current transfer */
549  master->status = STATUS_TIMEOUT;
550  FLEXIO_I2C_DRV_MasterStopTransfer(master);
551  }
552 
553  return master->status;
554 }
555 
556 
557 /*FUNCTION**********************************************************************
558  *
559  * Function Name : FLEXIO_I2C_DRV_MasterCheckNack
560  * Description : Checks if the current Rx shifter error is NACK or RX_OVERFLOW
561  *
562  * If there is a Tx event active it is an indication that module was not
563  * serviced for a long time - chances are this is an overflow.
564  * It is not certain, and it is even possible to have both NACK and overflow,
565  * but there is no way to tell, so we chose the safe option (if it is an
566  * overflow and we abort the transfer we may block the I2C bus).
567  *
568  *
569  *END**************************************************************************/
570 static inline bool FLEXIO_I2C_DRV_MasterCheckNack(const FLEXIO_Type *baseAddr, const flexio_i2c_master_state_t *master)
571 {
572  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
573 
574  resourceIndex = master->flexioCommon.resourceIndex;
575  return !(FLEXIO_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)));
576 }
577 
578 
579 /*FUNCTION**********************************************************************
580  *
581  * Function Name : FLEXIO_I2C_DRV_MasterBusBusy
582  * Description : Check status of the I2C bus.
583  * If either SDA or SCL is low, the bus is busy.
584  *
585  *END**************************************************************************/
586 static inline bool FLEXIO_I2C_DRV_MasterBusBusy(const FLEXIO_Type *baseAddr, const flexio_i2c_master_state_t *master)
587 {
588  uint8_t pinMask = (uint8_t)((1U << master->sdaPin) | (1U << master->sclPin));
589  if ((FLEXIO_GetPinData(baseAddr) & pinMask) == pinMask)
590  {
591  /* both pins are high, bus is not busy */
592  return false;
593  }
594  else
595  {
596  /* bus is busy */
597  return true;
598  }
599 }
600 
601 
602 /*FUNCTION**********************************************************************
603  *
604  * Function Name : FLEXIO_I2C_DRV_MasterCheckStatus
605  * Description : Check status of the I2C transfer. This function can be
606  * called either in an interrupt routine or directly in polling
607  * mode to advance the I2C transfer.
608  *
609  *END**************************************************************************/
610 static void FLEXIO_I2C_DRV_MasterCheckStatus(void *stateStruct)
611 {
612  FLEXIO_Type *baseAddr;
613  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
615 
616  DEV_ASSERT(stateStruct != NULL);
617 
618  master = (flexio_i2c_master_state_t *)stateStruct;
619  baseAddr = g_flexioBase[master->flexioCommon.instance];
620  resourceIndex = master->flexioCommon.resourceIndex;
621 
622  /* Check for errors */
623  if (FLEXIO_GetShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex)))
624  {
625  master->status = STATUS_I2C_TX_UNDERRUN;
626  FLEXIO_ClearShifterErrorStatus(baseAddr, TX_SHIFTER(resourceIndex));
627  /* don't stop the transfer, continue processing events */
628  }
629  if (FLEXIO_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
630  {
631  /* Device limitation: not possible to tell the difference between NACK and receive overflow */
632  if (FLEXIO_I2C_DRV_MasterCheckNack(baseAddr, master))
633  {
634  master->status = STATUS_I2C_RECEIVED_NACK;
635  /* Force the transfer to stop */
636  FLEXIO_I2C_DRV_MasterStopTransfer(master);
637  /* Call callback to announce the event to the user */
638  if (master->callback != NULL)
639  {
640  master->callback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
641  }
642  return;
643  }
644  else
645  {
646  master->status = STATUS_I2C_RX_OVERRUN;
647  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
648  /* don't stop the transfer, continue processing events */
649  }
650  }
651  /* Check if data was received */
652  if (FLEXIO_GetShifterStatus(baseAddr, RX_SHIFTER(resourceIndex)))
653  {
654  FLEXIO_I2C_DRV_ReadData(master);
655  }
656  /* Check if the transfer is over */
657  if (FLEXIO_GetTimerStatus(baseAddr, SCL_TIMER(resourceIndex)))
658  {
659  /* Clear timer status */
660  FLEXIO_ClearTimerStatus(baseAddr, SCL_TIMER(resourceIndex));
661  /* Record success if there was no error */
662  if (master->status == STATUS_BUSY)
663  {
664  master->status = STATUS_SUCCESS;
665  }
666  /* End transfer. In case of race condition between Tx_shifter and timer_end events,
667  it is possible for the clock to be restarted. So we use forced stop to avoid this. */
668  FLEXIO_I2C_DRV_MasterStopTransfer(master);
669  /* Call callback to announce the event to the user */
670  if (master->callback != NULL)
671  {
672  master->callback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
673  }
674  /* Skip checking Tx event if transfer is over */
675  return;
676  }
677  /* Check if transmitter needs more data */
678  if (FLEXIO_GetShifterStatus(baseAddr, TX_SHIFTER(resourceIndex)))
679  {
680  FLEXIO_I2C_DRV_WriteData(master);
681  if (master->txRemainingBytes == 0U)
682  {
683  /* Done transmitting, disable Tx interrupt */
684  FLEXIO_SetShifterInterrupt(baseAddr, (uint8_t)(1U << TX_SHIFTER(resourceIndex)), false);
685  }
686  }
687 }
688 
689 
690 /*FUNCTION**********************************************************************
691  *
692  * Function Name : FLEXIO_I2C_DRV_MasterComputeTxRegAddr
693  * Description : Computes the address of the register used for DMA tx transfer
694  *
695  *END**************************************************************************/
696 static inline uint32_t FLEXIO_I2C_DRV_MasterComputeTxRegAddr(const flexio_i2c_master_state_t *master)
697 {
698  uint32_t addr;
699  const FLEXIO_Type *baseAddr;
700  uint8_t shifter;
701 
702  baseAddr = g_flexioBase[master->flexioCommon.instance];
703  shifter = TX_SHIFTER(master->flexioCommon.resourceIndex);
704  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter])) + (sizeof(uint32_t) - 1U);
705  return addr;
706 }
707 
708 
709 /*FUNCTION**********************************************************************
710  *
711  * Function Name : FLEXIO_I2C_DRV_MasterComputeRxRegAddr
712  * Description : Computes the address of the register used for DMA rx transfer
713  *
714  *END**************************************************************************/
715 static inline uint32_t FLEXIO_I2C_DRV_MasterComputeRxRegAddr(const flexio_i2c_master_state_t *master)
716 {
717  uint32_t addr;
718  const FLEXIO_Type *baseAddr;
719  uint8_t shifter;
720 
721  baseAddr = g_flexioBase[master->flexioCommon.instance];
722  shifter = RX_SHIFTER(master->flexioCommon.resourceIndex);
723  addr = (uint32_t)(&(baseAddr->SHIFTBUFBIS[shifter]));
724  return addr;
725 }
726 
727 
728 /*FUNCTION**********************************************************************
729  *
730  * Function Name : FLEXIO_I2C_DRV_MasterDmaBlockImmediate
731  * Description : Configures a DMA transfer to trigger immediately
732  *
733  *END**************************************************************************/
734 static inline void FLEXIO_I2C_DRV_MasterDmaBlockImmediate(edma_software_tcd_t *stcdBase, uint8_t blockNo)
735 {
736  /* Set the START bit for this TCD to 1 */
737  stcdBase[blockNo].CSR |= (uint16_t)DMA_TCD_CSR_START(1U);
738 }
739 
740 
741 /*FUNCTION**********************************************************************
742  *
743  * Function Name : FLEXIO_I2C_DRV_MasterDmaBlockTerminate
744  * Description : Configures a DMA transfer to disable the DMArequuest upon transfer completion
745  *
746  *END**************************************************************************/
747 static inline void FLEXIO_I2C_DRV_MasterDmaBlockTerminate(edma_software_tcd_t *stcdBase, uint8_t blockNo)
748 {
749  /* Set the DREQ bit for this TCD to 1 */
750  stcdBase[blockNo].CSR |= (uint16_t)DMA_TCD_CSR_DREQ(1U);
751 }
752 
753 
754 /*FUNCTION**********************************************************************
755  *
756  * Function Name : FLEXIO_I2C_DRV_MasterDmaConfigTx
757  * Description : Configures DMA transfer for Tx
758  *
759  *END**************************************************************************/
760 static inline void FLEXIO_I2C_DRV_MasterDmaConfigTx(flexio_i2c_master_state_t *master,
761  edma_software_tcd_t *stcdBase)
762 {
763  edma_scatter_gather_list_t srcList[2U];
764  edma_scatter_gather_list_t destList[2U];
765  uint32_t addr;
766 
767  /* Configure Tx chain */
768  /* First block: transmit data */
769  if (master->receive == false)
770  {
771  addr = (uint32_t)(master->data);
772  }
773  else
774  {
775  /* if receiving, send 0xFF to keep the line clear */
776  master->dummyDmaIdle = 0xFFU;
777  addr = (uint32_t)(&(master->dummyDmaIdle));
778  }
779  srcList[0U].address = addr;
780  srcList[0U].length = master->rxRemainingBytes;
781  srcList[0U].type = EDMA_TRANSFER_MEM2PERIPH;
782  destList[0U].address = FLEXIO_I2C_DRV_MasterComputeTxRegAddr(master);
783  destList[0U].length = master->rxRemainingBytes;
784  destList[0U].type = EDMA_TRANSFER_MEM2PERIPH;
785 
786  /* Second block: transmit stop/repeated start */
787  if (master->sendStop)
788  {
789  master->dummyDmaStop = 0U;
790  }
791  else
792  {
793  master->dummyDmaStop = 0xFFU;
794  }
795  srcList[1U].address = (uint32_t)(&(master->dummyDmaStop));
796  srcList[1U].length = 1U;
797  srcList[1U].type = EDMA_TRANSFER_MEM2PERIPH;
798  destList[1U].address = FLEXIO_I2C_DRV_MasterComputeTxRegAddr(master);
799  destList[1U].length = 1U;
800  destList[1U].type = EDMA_TRANSFER_MEM2PERIPH;
801 
802  /* use 2 STCDs for tx, transfer size: 1 byte, 1 byte per DMA request */
803  (void)EDMA_DRV_ConfigScatterGatherTransfer(master->txDMAChannel, stcdBase, EDMA_TRANSFER_SIZE_1B,
804  1U, srcList, destList, 2U);
805 
806  if (master->receive == true)
807  {
808  /* if there is no data to transmit, don't increment source offset */
809  EDMA_DRV_SetSrcOffset(master->txDMAChannel, 0);
810  }
811  /* set DREQ bit for last block */
812  FLEXIO_I2C_DRV_MasterDmaBlockTerminate(stcdBase, 0U);
813 }
814 
815 
816 /*FUNCTION**********************************************************************
817  *
818  * Function Name : FLEXIO_I2C_DRV_MasterDmaConfigRx
819  * Description : Configures DMA transfer for Rx
820  *
821  *END**************************************************************************/
822 static inline void FLEXIO_I2C_DRV_MasterDmaConfigRx(flexio_i2c_master_state_t *master,
823  edma_software_tcd_t *stcdBase)
824 {
825  edma_scatter_gather_list_t srcList[6U];
826  edma_scatter_gather_list_t destList[6U];
827  uint32_t tmp;
828  uint8_t blockCnt = 0U;
829  const FLEXIO_Type *baseAddr;
830  uint8_t shifter;
831  uint8_t dmaChn;
832 
833  baseAddr = g_flexioBase[master->flexioCommon.instance];
834  dmaChn = master->rxDMAChannel;
835 
836  /* Configure Rx chain */
837  if (master->receive == false)
838  {
839  /* when transmitting we don't need scatter-gather for receive, just move read data to dummy location */
840  (void)EDMA_DRV_ConfigMultiBlockTransfer(dmaChn,
842  FLEXIO_I2C_DRV_MasterComputeRxRegAddr(master),
843  (uint32_t)(&(master->dummyDmaReceive)),
845  1U, master->rxRemainingBytes + 1U, true);
846  /* no data to receive, don't increment destination offset */
847  EDMA_DRV_SetDestOffset(dmaChn, 0);
848  }
849  else
850  {
851  /* First block: receive address byte (dummy read) */
852  srcList[blockCnt].address = FLEXIO_I2C_DRV_MasterComputeRxRegAddr(master);
853  srcList[blockCnt].length = 1U;
854  srcList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
855  destList[blockCnt].address = (uint32_t)(&(master->dummyDmaReceive));
856  destList[blockCnt].length = 1U;
857  destList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
858  blockCnt++;
859  /* When receiving just 1 byte skip the "middle" part */
860  if (master->rxRemainingBytes > 1U)
861  {
862  /* Second block: set tx shifter stop bit to 0 (transmit ACK) */
863  shifter = TX_SHIFTER(master->flexioCommon.resourceIndex);
864  tmp = baseAddr->SHIFTCFG[shifter];
865  tmp &= ~(FLEXIO_SHIFTCFG_SSTOP_MASK);
866  tmp |= FLEXIO_SHIFTCFG_SSTOP(FLEXIO_SHIFTER_STOP_BIT_0);
867  master->dmaReceiveTxStop0 = (uint8_t)(tmp & 0xFFU);
868  srcList[blockCnt].address = (uint32_t)(&(master->dmaReceiveTxStop0));
869  srcList[blockCnt].length = 1U;
870  srcList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
871  destList[blockCnt].address = (uint32_t)(&(baseAddr->SHIFTCFG[shifter]));
872  destList[blockCnt].length = 1U;
873  destList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
874  blockCnt++;
875  /* Third block: receive all but the last data byte */
876  srcList[blockCnt].address = FLEXIO_I2C_DRV_MasterComputeRxRegAddr(master);
877  srcList[blockCnt].length = master->rxRemainingBytes - 1U;
878  srcList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
879  destList[blockCnt].address = (uint32_t)(master->data);
880  destList[blockCnt].length = master->rxRemainingBytes - 1U;
881  destList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
882  blockCnt++;
883  /* Fourth block: set tx shifter stop bit to 1 (transmit NACK for last byte) */
884  tmp = baseAddr->SHIFTCFG[shifter];
885  tmp &= ~(FLEXIO_SHIFTCFG_SSTOP_MASK);
886  tmp |= FLEXIO_SHIFTCFG_SSTOP(FLEXIO_SHIFTER_STOP_BIT_1);
887  master->dmaReceiveTxStop1 = (uint8_t)(tmp & 0xFFU);
888  srcList[blockCnt].address = (uint32_t)(&(master->dmaReceiveTxStop1));
889  srcList[blockCnt].length = 1U;
890  srcList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
891  destList[blockCnt].address = (uint32_t)(&(baseAddr->SHIFTCFG[shifter]));
892  destList[blockCnt].length = 1U;
893  destList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
894  blockCnt++;
895  }
896  /* Fifth block: set rx shifter stop bit to 1 (expect NACK) */
897  shifter = RX_SHIFTER(master->flexioCommon.resourceIndex);
898  tmp = baseAddr->SHIFTCFG[shifter];
899  tmp &= ~(FLEXIO_SHIFTCFG_SSTOP_MASK);
900  tmp |= FLEXIO_SHIFTCFG_SSTOP(FLEXIO_SHIFTER_STOP_BIT_1);
901  master->dmaReceiveRxStop1 = (uint8_t)(tmp & 0xFFU);
902  srcList[blockCnt].address = (uint32_t)(&(master->dmaReceiveRxStop1));
903  srcList[blockCnt].length = 1U;
904  srcList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
905  destList[blockCnt].address = (uint32_t)(&(baseAddr->SHIFTCFG[shifter]));
906  destList[blockCnt].length = 1U;
907  destList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
908  blockCnt++;
909  /* Sixth block: receive last byte */
910  srcList[blockCnt].address = FLEXIO_I2C_DRV_MasterComputeRxRegAddr(master);
911  srcList[blockCnt].length = 1U;
912  srcList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
913  destList[blockCnt].address = (uint32_t)(&(master->data[master->rxRemainingBytes - 1U]));
914  destList[blockCnt].length = 1U;
915  destList[blockCnt].type = EDMA_TRANSFER_PERIPH2MEM;
916  blockCnt++;
917 
918  /* use blockCnt (3 or 6) STCDs for rx, transfer size: 1 byte, 1 byte per DMA request */
920  stcdBase,
921  EDMA_TRANSFER_SIZE_1B, 1U, srcList, destList, blockCnt);
922 
923  /* set all config transfers to SHIFTCFG registers to trigger immediately */
924  FLEXIO_I2C_DRV_MasterDmaBlockImmediate(stcdBase, 0U);
925  if (master->rxRemainingBytes > 1U)
926  {
927  FLEXIO_I2C_DRV_MasterDmaBlockImmediate(stcdBase, 2U);
928  FLEXIO_I2C_DRV_MasterDmaBlockImmediate(stcdBase, 3U);
929  }
930  /* set DREQ bit for last block */
931  FLEXIO_I2C_DRV_MasterDmaBlockTerminate(stcdBase, (uint8_t)(blockCnt - 2U));
932  }
933 }
934 
935 
936 /*FUNCTION**********************************************************************
937  *
938  * Function Name : FLEXIO_I2C_DRV_MasterStartDmaTransfer
939  * Description : Starts a DMA transfer
940  *
941  *END**************************************************************************/
942 static void FLEXIO_I2C_DRV_MasterStartDmaTransfer(flexio_i2c_master_state_t *master)
943 {
944  uint32_t alignedStcd;
945  edma_software_tcd_t *stcdBase;
946 
947  /* get aligned address to use for software TCDs */
948  alignedStcd = STCD_ADDR(master->stcd);
949  stcdBase = (edma_software_tcd_t *)(alignedStcd);
950 
951  /* Configure Tx and Rx chains */
952  FLEXIO_I2C_DRV_MasterDmaConfigTx(master, stcdBase);
953  FLEXIO_I2C_DRV_MasterDmaConfigRx(master, &stcdBase[FLEXIO_I2C_DMA_TX_CHAIN_LENGTH]);
954 
955  /* Start both DMA channels */
956  (void)EDMA_DRV_StartChannel(master->txDMAChannel);
957  (void)EDMA_DRV_StartChannel(master->rxDMAChannel);
958 }
959 
960 
961 
962 /*FUNCTION**********************************************************************
963  *
964  * Function Name : FLEXIO_I2C_DRV_MasterEndDmaTransfer
965  * Description : Starts a DMA transfer
966  *
967  *END**************************************************************************/
968 static void FLEXIO_I2C_DRV_MasterEndDmaTransfer(void *stateStruct)
969 {
971  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
972  FLEXIO_Type *baseAddr;
973 
974  DEV_ASSERT(stateStruct != NULL);
975 
976  master = (flexio_i2c_master_state_t *)stateStruct;
977  baseAddr = g_flexioBase[master->flexioCommon.instance];
978  resourceIndex = master->flexioCommon.resourceIndex;
979 
980  /* Check for NACK */
981  if (FLEXIO_GetShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex)))
982  {
983  FLEXIO_ClearShifterErrorStatus(baseAddr, RX_SHIFTER(resourceIndex));
984  master->status = STATUS_I2C_RECEIVED_NACK;
985  /* Force the transfer to stop */
986  FLEXIO_I2C_DRV_MasterStopTransfer(master);
987  /* Call callback to announce the event to the user */
988  if (master->callback != NULL)
989  {
990  master->callback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
991  }
992  return;
993  }
994  /* Check if the transfer is over */
995  if (FLEXIO_GetTimerStatus(baseAddr, SCL_TIMER(resourceIndex)))
996  {
997  /* Clear timer status */
998  FLEXIO_ClearTimerStatus(baseAddr, SCL_TIMER(resourceIndex));
999  /* Record success if there was no error */
1000  if (master->status == STATUS_BUSY)
1001  {
1002  master->status = STATUS_SUCCESS;
1003  }
1004  /* End transfer */
1005  FLEXIO_I2C_DRV_MasterStopTransfer(master);
1006  /* Call callback to announce the event to the user */
1007  if (master->callback != NULL)
1008  {
1009  master->callback(I2C_MASTER_EVENT_END_TRANSFER, master->callbackParam);
1010  }
1011  }
1012 }
1013 
1014 
1015 /*FUNCTION**********************************************************************
1016  *
1017  * Function Name : FLEXIO_I2C_DRV_MasterStartTransfer
1018  * Description : Perform a send or receive transaction on the I2C bus
1019  *
1020  *END**************************************************************************/
1021 static status_t FLEXIO_I2C_DRV_MasterStartTransfer(flexio_i2c_master_state_t *master,
1022  uint8_t * buff,
1023  uint32_t size,
1024  bool sendStop,
1025  bool receive)
1026 {
1027  FLEXIO_Type *baseAddr;
1028  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1029 
1030  DEV_ASSERT(master != NULL);
1031 
1032  baseAddr = g_flexioBase[master->flexioCommon.instance];
1033  resourceIndex = master->flexioCommon.resourceIndex;
1034 
1035  /* Check if driver is busy */
1036  DEV_ASSERT(master->driverIdle);
1037  /* Check if transfer size is in admissible range */
1039 
1040  /* Check if bus is busy */
1041  if (FLEXIO_I2C_DRV_MasterBusBusy(baseAddr, master))
1042  {
1043  return STATUS_I2C_BUS_BUSY;
1044  }
1045 
1046  /* Initialize transfer data */
1047  master->data = (uint8_t *)buff;
1048  /* Tx - one extra byte for stop condition */
1049  master->txRemainingBytes = size + 1U;
1050  master->rxRemainingBytes = size;
1051  master->status = STATUS_BUSY;
1052  master->driverIdle = false;
1053  master->sendStop = sendStop;
1054  master->receive = receive;
1055  master->addrReceived = false;
1056 
1057  /* Configure device for requested number of bytes, keeping the existing baud rate */
1058  FLEXIO_I2C_DRV_MasterSetBytesNo(baseAddr, master);
1059  /* Enable timers and shifters */
1060  FLEXIO_I2C_DRV_MasterEnableTransfer(master);
1061  /* Enable transfer engine */
1062  switch (master->driverType)
1063  {
1065  /* Send address to start transfer */
1066  FLEXIO_I2C_DRV_MasterSendAddress(baseAddr, master);
1067  /* Enable interrupt for Tx and Rx shifters */
1068  FLEXIO_SetShifterInterrupt(baseAddr,
1069  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
1070  true);
1071  FLEXIO_SetShifterErrorInterrupt(baseAddr,
1072  (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))),
1073  true);
1074  /* Enable interrupt for SCL timer */
1075  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << SCL_TIMER(resourceIndex)), true);
1076  break;
1078  /* Send address to start transfer */
1079  FLEXIO_I2C_DRV_MasterSendAddress(baseAddr, master);
1080  /* Nothing to do here, FLEXIO_I2C_DRV_MasterGetStatus() will handle the transfer */
1081  break;
1083  FLEXIO_I2C_DRV_MasterStartDmaTransfer(master);
1084  /* Enable error interrupt for Rx shifter - for NACK detection */
1085  FLEXIO_SetShifterErrorInterrupt(baseAddr, (uint8_t)(1U << RX_SHIFTER(resourceIndex)), true);
1086  /* Enable interrupt for SCL timer - for end of transfer detection */
1087  FLEXIO_SetTimerInterrupt(baseAddr, (uint8_t)(1U << SCL_TIMER(resourceIndex)), true);
1088  /* Send address to start transfer */
1089  FLEXIO_I2C_DRV_MasterSendAddress(baseAddr, master);
1090  /* Enable FlexIO DMA requests for both shifters */
1091  FLEXIO_SetShifterDMARequest(baseAddr, (uint8_t)((1U << TX_SHIFTER(resourceIndex)) | (1U << RX_SHIFTER(resourceIndex))), true);
1092  break;
1093  default:
1094  /* Impossible type - do nothing */
1095  break;
1096  }
1097 
1098  return STATUS_SUCCESS;
1099 }
1100 
1103 /*******************************************************************************
1104  * Code
1105  ******************************************************************************/
1106 
1107 /*FUNCTION**********************************************************************
1108  *
1109  * Function Name : FLEXIO_I2C_DRV_MasterInit
1110  * Description : Initialize the FLEXIO_I2C master mode driver
1111  * Implements : FLEXIO_I2C_DRV_MasterInit_Activity
1112  *
1113  *END**************************************************************************/
1115  const flexio_i2c_master_user_config_t * userConfigPtr,
1116  flexio_i2c_master_state_t * master)
1117 {
1118  uint32_t inputClock;
1119  status_t clkErr;
1120  status_t retCode;
1121  status_t osifError = STATUS_SUCCESS;
1122  uint8_t dmaReqTx;
1123  uint8_t dmaReqRx;
1124 
1125  DEV_ASSERT(master != NULL);
1126  DEV_ASSERT(instance < FLEXIO_INSTANCE_COUNT);
1127 
1128  /* Check that device was initialized */
1129  DEV_ASSERT(g_flexioDeviceStatePtr[instance] != NULL);
1130 
1131  /* Get the protocol clock frequency */
1132  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[instance], &inputClock);
1133  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1134  DEV_ASSERT(inputClock > 0U);
1135 
1136  /* Instruct the resource allocator that we need two shifters/timers */
1137  master->flexioCommon.resourceCount = 2U;
1138  /* Common FlexIO driver initialization */
1139  retCode = FLEXIO_DRV_InitDriver(instance, &(master->flexioCommon));
1140  if (retCode != STATUS_SUCCESS)
1141  { /* Initialization failed, not enough resources */
1142  return retCode;
1143  }
1144 
1145  /* Initialize the semaphore */
1146  if (userConfigPtr->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1147  {
1148  osifError = OSIF_SemaCreate(&(master->idleSemaphore), 0U);
1149  DEV_ASSERT(osifError == STATUS_SUCCESS);
1150  }
1151 
1152  /* Initialize driver-specific context structure */
1153  master->driverType = userConfigPtr->driverType;
1154  master->slaveAddress = userConfigPtr->slaveAddress;
1155  master->sdaPin = userConfigPtr->sdaPin;
1156  master->sclPin = userConfigPtr->sclPin;
1157  master->callback = userConfigPtr->callback;
1158  master->callbackParam = userConfigPtr->callbackParam;
1159  master->blocking = false;
1160  master->driverIdle = true;
1161  master->status = STATUS_SUCCESS;
1162 
1163  /* Configure device for I2C mode */
1164  FLEXIO_I2C_DRV_MasterConfigure(master, inputClock, userConfigPtr->baudRate);
1165 
1166  /* Set up transfer engine */
1167  switch (master->driverType)
1168  {
1170  master->flexioCommon.isr = FLEXIO_I2C_DRV_MasterCheckStatus;
1171  break;
1173  /* Nothing to do here, FLEXIO_I2C_DRV_MasterGetStatus() will handle the transfer */
1174  break;
1176  /* Store DMA channel numbers */
1177  master->txDMAChannel = userConfigPtr->txDMAChannel;
1178  master->rxDMAChannel = userConfigPtr->rxDMAChannel;
1179  /* Configure DMA request sources */
1180  dmaReqTx = g_flexioDMASrc[instance][TX_SHIFTER(master->flexioCommon.resourceIndex)];
1181  dmaReqRx = g_flexioDMASrc[instance][RX_SHIFTER(master->flexioCommon.resourceIndex)];
1182  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->txDMAChannel, dmaReqTx);
1183  (void)EDMA_DRV_SetChannelRequest(userConfigPtr->rxDMAChannel, dmaReqRx);
1184  /* For DMA transfers we use timer interrupts to signal transfer end */
1185  master->flexioCommon.isr = FLEXIO_I2C_DRV_MasterEndDmaTransfer;
1186  break;
1187  default:
1188  /* Impossible type - do nothing */
1189  break;
1190  }
1191 
1192  (void)clkErr;
1193  (void)osifError;
1194  return STATUS_SUCCESS;
1195 }
1196 
1197 
1198 /*FUNCTION**********************************************************************
1199  *
1200  * Function Name : FLEXIO_I2C_DRV_MasterDeinit
1201  * Description : De-initialize the FLEXIO_I2C master mode driver
1202  * Implements : FLEXIO_I2C_DRV_MasterDeinit_Activity
1203  *
1204  *END**************************************************************************/
1206 {
1207  DEV_ASSERT(master != NULL);
1208 
1209  /* Check if driver is busy */
1210  DEV_ASSERT(master->driverIdle);
1211 
1212  /* Destroy the semaphore */
1213  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1214  {
1215  (void)OSIF_SemaDestroy(&(master->idleSemaphore));
1216  }
1217  return FLEXIO_DRV_DeinitDriver(&(master->flexioCommon));
1218 }
1219 
1220 
1221 /*FUNCTION**********************************************************************
1222  *
1223  * Function Name : FLEXIO_I2C_DRV_MasterSetBaudRate
1224  * Description : Set the baud rate for any subsequent I2C communication
1225  * Implements : FLEXIO_I2C_DRV_MasterSetBaudRate_Activity
1226  *
1227  *END**************************************************************************/
1229 {
1230  FLEXIO_Type *baseAddr;
1231  uint16_t divider;
1232  uint16_t timerCmp;
1233  uint32_t inputClock;
1234  status_t clkErr;
1235  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1236 
1237  DEV_ASSERT(master != NULL);
1238 
1239  baseAddr = g_flexioBase[master->flexioCommon.instance];
1240  resourceIndex = master->flexioCommon.resourceIndex;
1241 
1242  /* Check if driver is busy */
1243  DEV_ASSERT(master->driverIdle);
1244  /* Get the protocol clock frequency */
1245  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1246  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1247  DEV_ASSERT(inputClock > 0U);
1248 
1249  /* Compute divider */
1250  FLEXIO_I2C_DRV_MasterComputeBaudRateDivider(baudRate, &divider, inputClock);
1251 
1252  /* Configure timer divider in the lower 8 bits of TIMCMP[CMP] */
1253  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCL_TIMER(resourceIndex));
1254  timerCmp = (uint16_t)((timerCmp & 0xFF00U) | divider);
1255  FLEXIO_SetTimerCompare(baseAddr, SCL_TIMER(resourceIndex), timerCmp);
1256 
1257  (void)clkErr;
1258  return STATUS_SUCCESS;
1259 }
1260 
1261 
1262 /*FUNCTION**********************************************************************
1263  *
1264  * Function Name : FLEXIO_I2C_DRV_MasterGetBaudRate
1265  * Description : Get the currently configured baud rate
1266  * Implements : FLEXIO_I2C_DRV_MasterGetBaudRate_Activity
1267  *
1268  *END**************************************************************************/
1270 {
1271  const FLEXIO_Type *baseAddr;
1272  uint32_t inputClock;
1273  uint16_t divider;
1274  uint16_t timerCmp;
1275  status_t clkErr;
1276  uint8_t resourceIndex; /* Index of first used internal resource instance (shifter and timer) */
1277 
1278  DEV_ASSERT(master != NULL);
1279  DEV_ASSERT(baudRate != NULL);
1280 
1281  baseAddr = g_flexioBase[master->flexioCommon.instance];
1282  resourceIndex = master->flexioCommon.resourceIndex;
1283 
1284  /* Get the protocol clock frequency */
1285  clkErr = CLOCK_SYS_GetFreq(g_flexioClock[master->flexioCommon.instance], &inputClock);
1286  DEV_ASSERT(clkErr == STATUS_SUCCESS);
1287  DEV_ASSERT(inputClock > 0U);
1288 
1289  /* Get the currently configured divider */
1290  timerCmp = FLEXIO_GetTimerCompare(baseAddr, SCL_TIMER(resourceIndex));
1291  divider = (uint16_t)(timerCmp & 0x00FFU);
1292 
1293  /* Compute baud rate: input_clock / (2 * (divider + 2)). Round to nearest integer */
1294  *baudRate = (inputClock + divider + 2U) / (2U * ((uint32_t)divider + 2U));
1295 
1296  (void)clkErr;
1297  return STATUS_SUCCESS;
1298 }
1299 
1300 
1301 /*FUNCTION**********************************************************************
1302  *
1303  * Function Name : FLEXIO_I2C_DRV_MasterSetSlaveAddr
1304  * Description : Set the slave address for any subsequent I2C communication
1305  * Implements : FLEXIO_I2C_DRV_MasterSetSlaveAddr_Activity
1306  *
1307  *END**************************************************************************/
1309 {
1310  DEV_ASSERT(master != NULL);
1311 
1312  /* Check if driver is busy */
1313  DEV_ASSERT(master->driverIdle);
1314 
1315  master->slaveAddress = address;
1316  return STATUS_SUCCESS;
1317 }
1318 
1319 
1320 /*FUNCTION**********************************************************************
1321  *
1322  * Function Name : FLEXIO_I2C_DRV_MasterSendData
1323  * Description : Perform a non-blocking send transaction on the I2C bus
1324  * Implements : FLEXIO_I2C_DRV_MasterSendData_Activity
1325  *
1326  *END**************************************************************************/
1328  const uint8_t * txBuff,
1329  uint32_t txSize,
1330  bool sendStop)
1331 {
1332  DEV_ASSERT(master != NULL);
1333  DEV_ASSERT(txBuff != NULL);
1334  DEV_ASSERT(txSize > 0U);
1335 
1336  return FLEXIO_I2C_DRV_MasterStartTransfer(master, (uint8_t *)txBuff, txSize, sendStop, false);
1337 }
1338 
1339 
1340 /*FUNCTION**********************************************************************
1341  *
1342  * Function Name : FLEXIO_I2C_DRV_MasterSendDataBlocking
1343  * Description : Perform a blocking send transaction on the I2C bus
1344  * Implements : FLEXIO_I2C_DRV_MasterSendDataBlocking_Activity
1345  *
1346  *END**************************************************************************/
1348  const uint8_t * txBuff,
1349  uint32_t txSize,
1350  bool sendStop,
1351  uint32_t timeout)
1352 {
1353  status_t status;
1354 
1355  DEV_ASSERT(master != NULL);
1356  DEV_ASSERT(txBuff != NULL);
1357  DEV_ASSERT(txSize > 0U);
1358 
1359  /* Mark transfer as blocking */
1360  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1361  {
1362  master->blocking = true;
1363  }
1364  /* Start the transfer */
1365  status = FLEXIO_I2C_DRV_MasterStartTransfer(master, (uint8_t *)txBuff, txSize, sendStop, false);
1366  if (status != STATUS_SUCCESS)
1367  {
1368  /* Transfer could not be started */
1369  master->blocking = false;
1370  return status;
1371  }
1372 
1373  /* Wait for transfer to end */
1374  return FLEXIO_I2C_DRV_MasterWaitTransferEnd(master, timeout);
1375 }
1376 
1377 
1378 /*FUNCTION**********************************************************************
1379  *
1380  * Function Name : FLEXIO_I2C_DRV_MasterReceiveData
1381  * Description : Perform a non-blocking receive transaction on the I2C bus
1382  * Implements : FLEXIO_I2C_DRV_MasterReceiveData_Activity
1383  *
1384  *END**************************************************************************/
1386  uint8_t * rxBuff,
1387  uint32_t rxSize,
1388  bool sendStop)
1389 {
1390  DEV_ASSERT(master != NULL);
1391  DEV_ASSERT(rxBuff != NULL);
1392  DEV_ASSERT(rxSize > 0U);
1393 
1394  return FLEXIO_I2C_DRV_MasterStartTransfer(master, rxBuff, rxSize, sendStop, true);
1395 }
1396 
1397 
1398 /*FUNCTION**********************************************************************
1399  *
1400  * Function Name : FLEXIO_I2C_DRV_MasterReceiveDataBlocking
1401  * Description : Perform a blocking receive transaction on the I2C bus
1402  * Implements : FLEXIO_I2C_DRV_MasterReceiveDataBlocking_Activity
1403  *
1404  *END**************************************************************************/
1406  uint8_t * rxBuff,
1407  uint32_t rxSize,
1408  bool sendStop,
1409  uint32_t timeout)
1410 {
1411  status_t status;
1412 
1413  DEV_ASSERT(master != NULL);
1414  DEV_ASSERT(rxBuff != NULL);
1415  DEV_ASSERT(rxSize > 0U);
1416 
1417  /* Mark transfer as blocking */
1418  if (master->driverType != FLEXIO_DRIVER_TYPE_POLLING)
1419  {
1420  master->blocking = true;
1421  }
1422  /* Start the transfer */
1423  status = FLEXIO_I2C_DRV_MasterStartTransfer(master, rxBuff, rxSize, sendStop, true);
1424  if (status != STATUS_SUCCESS)
1425  {
1426  /* Transfer could not be started */
1427  master->blocking = false;
1428  return status;
1429  }
1430 
1431  /* Wait for transfer to end */
1432  return FLEXIO_I2C_DRV_MasterWaitTransferEnd(master, timeout);
1433 }
1434 
1435 
1436 /*FUNCTION**********************************************************************
1437  *
1438  * Function Name : FLEXIO_I2C_DRV_MasterTransferAbort
1439  * Description : Aborts a non-blocking I2C master transaction
1440  * Implements : FLEXIO_I2C_DRV_MasterTransferAbort_Activity
1441  *
1442  *END**************************************************************************/
1444 {
1445  DEV_ASSERT(master != NULL);
1446 
1447  /* Warning: an ongoing transfer can't be aborted safely due to device limitation;
1448  there is no way to know the exact stage of the transfer, and if we disable the module
1449  during the ACK bit (transmit) or during a 0 data bit (receive) the slave will hold
1450  the SDA line low forever and block the I2C bus. NACK reception is the only exception,
1451  as there is no slave to hold the line low. Therefore this function should only be used
1452  in extreme circumstances, and the application must have a way to reset the I2C slave
1453  */
1454 
1455  /* Check if driver is busy */
1456  if (master->driverIdle)
1457  {
1458  return STATUS_SUCCESS;
1459  }
1460 
1461  master->status = STATUS_I2C_ABORTED;
1462  FLEXIO_I2C_DRV_MasterStopTransfer(master);
1463 
1464  return STATUS_SUCCESS;
1465 }
1466 
1467 
1468 /*FUNCTION**********************************************************************
1469  *
1470  * Function Name : FLEXIO_I2C_DRV_MasterGetStatus
1471  * Description : Get the status of the current non-blocking I2C master transaction
1472  * Implements : FLEXIO_I2C_DRV_MasterGetStatus_Activity
1473  *
1474  *END**************************************************************************/
1476 {
1477  uint32_t remainingBytes;
1478 
1479  DEV_ASSERT(master != NULL);
1480 
1481  /* Use rxRemainingBytes even for transmit; byte is not transmitted
1482  until rx shifter confirms the ACK */
1483  remainingBytes = master->rxRemainingBytes;
1484 
1485  if (!master->driverIdle)
1486  {
1487  switch(master->driverType)
1488  {
1490  /* In polling mode advance the I2C transfer here */
1491  FLEXIO_I2C_DRV_MasterCheckStatus(master);
1492  break;
1493 
1495  /* In DMA mode just update the remaining count.
1496  DO NOT write master->rxRemainingBytes directly !!! */
1497  remainingBytes = EDMA_DRV_GetRemainingMajorIterationsCount(master->rxDMAChannel);
1498  break;
1499 
1500  default:
1501  /* Nothing */
1502  break;
1503  }
1504 
1505  }
1506 
1507  if (bytesRemaining != NULL)
1508  {
1509  *bytesRemaining = remainingBytes;
1510  }
1511 
1512  if (!master->driverIdle)
1513  {
1514  return STATUS_BUSY;
1515  }
1516  else
1517  {
1518  return master->status;
1519  }
1520 }
1521 
1522 
1523 /*******************************************************************************
1524  * EOF
1525  ******************************************************************************/
eDMA TCD Implements : edma_software_tcd_t_Class
Definition: edma_driver.h:397
uint32_t EDMA_DRV_GetRemainingMajorIterationsCount(uint8_t virtualChannel)
Returns the remaining major loop iteration count.
Definition: edma_driver.c:1346
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
#define FLEXIO_I2C_MAX_SIZE
Maximum size of a transfer. The restriction is that the total number of SCL edges must not exceed 8 b...
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
#define FLEXIO_INSTANCE_COUNT
Definition: S32K118.h:3350
status_t FLEXIO_I2C_DRV_MasterInit(uint32_t instance, const flexio_i2c_master_user_config_t *userConfigPtr, flexio_i2c_master_state_t *master)
Initialize the FLEXIO_I2C master mode driver.
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
status_t FLEXIO_DRV_DeinitDriver(const flexio_common_state_t *driver)
void EDMA_DRV_SetDestOffset(uint8_t virtualChannel, int16_t offset)
Configures the destination address signed offset for the eDMA channel.
Definition: edma_driver.c:1226
status_t FLEXIO_I2C_DRV_MasterGetBaudRate(flexio_i2c_master_state_t *master, uint32_t *baudRate)
Get the currently configured baud rate.
volatile uint32_t SHIFTCFG[4u]
Definition: S32K118.h:3332
status_t EDMA_DRV_StopChannel(uint8_t virtualChannel)
Stops the eDMA channel.
Definition: edma_driver.c:952
#define DEV_ASSERT(x)
Definition: devassert.h:77
#define STCD_ADDR(address)
Definition: edma_driver.h:60
volatile uint32_t SHIFTBUFBIS[4u]
Definition: S32K118.h:3336
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
const clock_names_t g_flexioClock[(1u)]
Definition: flexio_common.c:65
status_t FLEXIO_I2C_DRV_MasterSetSlaveAddr(flexio_i2c_master_state_t *master, uint16_t address)
Set the slave address for any subsequent I2C communication.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
FLEXIO_Type *const g_flexioBase[(1u)]
Definition: flexio_common.c:56
void EDMA_DRV_SetSrcOffset(uint8_t virtualChannel, int16_t offset)
Configures the source address signed offset for the eDMA channel.
Definition: edma_driver.c:1076
Data structure for configuring a discrete memory transfer. Implements : edma_scatter_gather_list_t_Cl...
Definition: edma_driver.h:315
status_t FLEXIO_I2C_DRV_MasterDeinit(flexio_i2c_master_state_t *master)
De-initialize the FLEXIO_I2C master mode driver.
const uint8_t g_flexioDMASrc[(1u)][(4U)]
Definition: flexio_common.c:68
#define FLEXIO_SHIFTCFG_SSTOP(x)
Definition: S32K118.h:3502
status_t FLEXIO_DRV_InitDriver(uint32_t instance, flexio_common_state_t *driver)
edma_transfer_type_t type
Definition: edma_driver.h:318
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
status_t EDMA_DRV_ConfigScatterGatherTransfer(uint8_t virtualChannel, edma_software_tcd_t *stcd, edma_transfer_size_t transferSize, uint32_t bytesOnEachRequest, const edma_scatter_gather_list_t *srcList, const edma_scatter_gather_list_t *destList, uint8_t tcdCount)
Configures the DMA transfer in a scatter-gather mode.
Definition: edma_driver.c:761
flexio_device_state_t * g_flexioDeviceStatePtr[(1u)]
Definition: flexio_common.c:59
#define DMA_TCD_CSR_START(x)
Definition: S32K118.h:2992
status_t FLEXIO_I2C_DRV_MasterSetBaudRate(flexio_i2c_master_state_t *master, uint32_t baudRate)
Set the baud rate for any subsequent I2C communication.
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
Master internal context structure.
#define FLEXIO_SHIFTCFG_SSTOP_MASK
Definition: S32K118.h:3499
status_t EDMA_DRV_SetChannelRequest(uint8_t virtualChannel, uint8_t req)
Configures the DMA request for the eDMA channel.
Definition: edma_driver.c:983
Master configuration structure.
status_t FLEXIO_I2C_DRV_MasterSendDataBlocking(flexio_i2c_master_state_t *master, const uint8_t *txBuff, uint32_t txSize, bool sendStop, uint32_t timeout)
Perform a blocking send transaction on the I2C bus.
status_t FLEXIO_I2C_DRV_MasterReceiveDataBlocking(flexio_i2c_master_state_t *master, uint8_t *rxBuff, uint32_t rxSize, bool sendStop, uint32_t timeout)
Perform a blocking receive transaction on the I2C bus.
status_t FLEXIO_I2C_DRV_MasterTransferAbort(flexio_i2c_master_state_t *master)
Aborts a non-blocking I2C master transaction.
status_t FLEXIO_I2C_DRV_MasterReceiveData(flexio_i2c_master_state_t *master, uint8_t *rxBuff, uint32_t rxSize, bool sendStop)
Perform a non-blocking receive transaction on the I2C bus.
status_t FLEXIO_I2C_DRV_MasterGetStatus(flexio_i2c_master_state_t *master, uint32_t *bytesRemaining)
Get the status of the current non-blocking I2C master transaction.
status_t FLEXIO_I2C_DRV_MasterSendData(flexio_i2c_master_state_t *master, const uint8_t *txBuff, uint32_t txSize, bool sendStop)
Perform a non-blocking send transaction on the I2C bus.
#define DMA_TCD_CSR_DREQ(x)
Definition: S32K118.h:3004