ADuCM4x50 Device Drivers API Reference Manual  Release 4.0.0.0
adi_i2c.c
1 
29 #include <adi_processor.h>
30 #include <assert.h>
31 #include <string.h> /* for "memset" */
34 #include <drivers/general/adi_drivers_general.h>
35 #include <drivers/i2c/adi_i2c.h>
36 
39 #include <drivers/pwr/adi_pwr.h>
40 
41 #ifdef __ICCARM__
42 /*
43 * IAR MISRA C 2004 error suppressions.
44 *
45 *
46 * Pm011 (rule 6.3): Types which specify sign and size should be used
47 * We use bool which is accepted by MISRA but the toolchain does not accept it
48 *
49 * Pm123 (rule 8.5): there shall be no definition of objects or functions in a header file
50 * It is used in the _data.h file which isn't a header as such.
51 *
52 * Pm073 (rule 14.7): a function should have a single point of exit
53 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
54 * Multiple returns are used for error handling.
55 *
56 * Pm088 (rule 17.4): pointer arithmetic should not be used.
57 * Relying on pointer arithmetic for buffer handling.
58 *
59 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
60 * The rule makes an exception for memory-mapped register accesses.
61 */
62 
63 #pragma diag_suppress=Pm011,Pm123,Pm073,Pm143,Pm088,Pm140
64 #endif /* __ICCARM__ */
65 
66 /* pull in internal data structures */
67 #include "adi_i2c_data.c"
68 
69 
70 /* handy type-safe zero */
71 uint16_t uZero16 = 0u;
72 
73 /* central busy checker */
74 #define I2C_BUSY (uZero16 != ((hDevice->pDev->MSTAT) & (uint16_t)(BITM_I2C_MSTAT_MBUSY | BITM_I2C_MSTAT_LINEBUSY)))
75 
79  #define READ_NOT_WRITE (1u)
80 
81 /* Override "weak" default binding in startup.c */
83 extern void I2C0_Master_Int_Handler(void);
84 
85 /* DS4 and DS5 bits of GPIO Port 0 drive strength select register */
86 #define I2C_GPIO_PORT0_DS4 ((uint16_t) ((uint16_t) 1<<4))
87 #define I2C_GPIO_PORT0_DS5 ((uint16_t) ((uint16_t) 1<<5))
88 
89 #define ADI_ADUCM302X_CHIPID_SI_1_2 0x284u
90 
92 #if defined(ADI_DEBUG)
93 /*
94  * Verifies a pointer to a driver points to one of the driver
95  * struct's internal to this file.
96  */
97 static bool IsDeviceHandle(ADI_I2C_HANDLE const hDevice);
98 static bool IsDeviceHandle(ADI_I2C_HANDLE const hDevice)
99 {
100  if ((i2c_device_info[0].hDevice != (hDevice)) && ((hDevice)->pDevInfo->hDevice != NULL)) {
101  return true;
102  } else {
103  return false;
104  }
105 }
106 #endif
107 
108 #if defined(__ADUCM302x__)
109 static ADI_SYS_REGISTERS adi_sys_base = { pADI_SYS };
110 #endif
111 
115 /**********************************************************************************\
116 |**********************************USER INTERFACE**********************************|
117 \**********************************************************************************/
118 
119 
151 ADI_I2C_RESULT adi_i2c_Open (uint32_t const DeviceNum, void* const pMemory, uint32_t const MemorySize, ADI_I2C_HANDLE* const phDevice) {
152 
153  /* make a device handle out of the user memory */
154  ADI_I2C_HANDLE hDevice = (ADI_I2C_HANDLE)pMemory;
155  #if defined(__ADUCM302x__)
156  /*
157  * I2C fix for Silicon Version 1.2
158  * Enable the drive strength of GPIO pins used for I2C communication.
159  */
160 
161  /* Get the pointer to the internal structure for System registers*/
162  ADI_SYS_REGISTERS *sys = &adi_sys_base;
163 
164  if( sys->pReg->CHIPID == ADI_ADUCM302X_CHIPID_SI_1_2 )
165  {
166  *((volatile uint32_t *)REG_GPIO0_DS) |= ( I2C_GPIO_PORT0_DS4 | I2C_GPIO_PORT0_DS5 );
167  }
168 
169  #endif
170 #if defined(ADI_DEBUG)
171  /* check requested device number */
172  if (DeviceNum >= (uint32_t)ADI_I2C_NUM_INSTANCES) {
174  }
175 
176  /* verify device is not already open */
177  if (i2c_device_info[DeviceNum].hDevice != NULL) {
178  return ADI_I2C_DEVICE_IN_USE;
179  }
180 
181  /* verify memory size macro value */
182  assert(ADI_I2C_MEMORY_SIZE == sizeof(ADI_I2C_DEV_DATA_TYPE));
183 
184  /* verify user-provided memory meets requirement */
185  if ((NULL == pMemory) || (MemorySize < (uint32_t)ADI_I2C_MEMORY_SIZE)) {
187  }
188 #endif
189 
190  /* store a bad handle in case of failure */
191  *phDevice = NULL;
192 
193  /*
194  * Link user memory (handle) to ADI_I2C_DEVICE_INFO data structure.
195  *
196  * ADI_I2C_DEVICE_INFO <==> ADI_I2C_HANDLE
197  *
198  * Clear the ADI_I2C_HANDLE memory. This also sets all bool
199  * structure members to false so we do not need to waste cycles
200  * setting these explicitly (e.g. hDevice->bRepearStart = false)
201  */
202  i2c_device_info[DeviceNum].hDevice = (ADI_I2C_DEV_DATA_TYPE *)pMemory;
203  memset(pMemory, 0, MemorySize);
204 
205  /* also link device handle within __ADI_I2C_DEV_DATA_TYPE data structure */
206  hDevice->pDevInfo = &i2c_device_info[DeviceNum];
207  /*
208  * Although the ADI_I2C_DEVICE_INFO struct has the physical device pointer
209  * for this instance, copying it to the ADI_I2C_HANDLE struct (in user memory)
210  * will minimize the runtime footprint and cycle count when accessing the I2C
211  * registers.
212  */
213  hDevice->pDev = i2c_device_info[DeviceNum].pDev;
214 
215  /* store a pointer to user's static configuration settings */
216  hDevice->pDevInfo->pConfig = (ADI_I2C_CONFIG*)&gConfigInfo[DeviceNum];
217 
218  /* create the semaphore */
219  SEM_CREATE(hDevice, "i2c_sem", ADI_I2C_SEMAPHORE_FAILED)
220  ;
221 
222  /* reset the driver and HW state */
223  ADI_I2C_RESULT ignore ADI_UNUSED_ATTRIBUTE = i2cReset(hDevice);
224 
225  /* store device handle into user handle */
226  *phDevice = (ADI_I2C_HANDLE)hDevice;
227 
228  return ADI_I2C_SUCCESS;
229 }
230 
231 
249 
250 #ifdef ADI_DEBUG
251  if (IsDeviceHandle(hDevice)) {
253  }
254 #endif
255 
256  /* destroy semaphore */
257  SEM_DELETE(hDevice,ADI_I2C_SEMAPHORE_FAILED)
258  ;
259 
260  /* reset the driver and HW state */
261  ADI_I2C_RESULT ignore ADI_UNUSED_ATTRIBUTE = i2cReset(hDevice);
262 
263  /* stub handle */
264  hDevice->pDevInfo->hDevice = NULL;
265 
266  return ADI_I2C_SUCCESS;
267 }
268 
269 
325 ADI_I2C_RESULT adi_i2c_ReadWrite (ADI_I2C_HANDLE const hDevice, ADI_I2C_TRANSACTION* const pTransaction, uint32_t* const pHwErrors) {
326 
327 #ifdef ADI_DEBUG
328  if (IsDeviceHandle(hDevice)) {
330  }
331  if (I2C_BUSY) {
332  return ADI_I2C_DEVICE_IN_USE;
333  }
334  /* NULL transaction data pointer or zero transaction data count */
335  if ((NULL == pTransaction->pData) || (0u == pTransaction->nDataSize)) {
337  }
338 #endif
339 
340  /* reset submit/get safeguard flag */
341  hDevice->bSubmitCalled = false;
342 
343  /* submit/commence the transaction */
344  submitTransaction(hDevice, pTransaction);
345 
346  /* block on internal transaction completion/error semaphore */
347  if (ADI_I2C_SUCCESS == hDevice->result) {
348 
349  SEM_PEND(hDevice, ADI_I2C_SEMAPHORE_FAILED);
350 
351  /* completion interrupt comes as FIFO unloads, but serialization may not be complete yet... */
352  /* must also wait for hardware busy status to clear before giving back control */
353  /* i.e., allow any transmit serialization to complete after last FIFO unload */
354  while (I2C_BUSY) {
355  ;
356  }
357  }
358 
359  /* copy out any hardware errors... */
360  *pHwErrors = hDevice->hwErrors;
361  if (0u != hDevice->hwErrors) {
362  /* set the HW error return code */
363  hDevice->result = ADI_I2C_HW_ERROR_DETECTED;
364  } else if (pTransaction->nDataSize > 0 && pTransaction->bReadNotWrite && (hDevice->pDev->ADDR1 & 0x1) == 0) {
365  /* A read was expected but was not performed */
366  hDevice->result = ADI_I2C_FAILURE;
367  }
368 
369  /* return transaction result code */
370  return hDevice->result;
371 }
372 
373 
424 
425 #ifdef ADI_DEBUG
426  if (IsDeviceHandle(hDevice)) {
428  }
429  if (I2C_BUSY) {
430  return ADI_I2C_DEVICE_IN_USE;
431  }
432  /* NULL transaction data pointer or zero transaction data count */
433  if ((NULL == pTransaction->pData) || (0u == pTransaction->nDataSize)) {
435  }
436 #endif
437 
438  /* set submit/get safeguard flag */
439  hDevice->bSubmitCalled = true;
440 
441  /* submit/commence the transaction */
442  submitTransaction(hDevice, pTransaction);
443 
444  /* no blocking on submit... just return the submit result */
445  return hDevice->result;
446 }
447 
448 
484 ADI_I2C_RESULT adi_i2c_IsBufferAvailable (ADI_I2C_HANDLE const hDevice, bool* const pbCompletionState) {
485 
486 #ifdef ADI_DEBUG
487  if (IsDeviceHandle(hDevice)) {
489  }
490 #endif
491 
492  /* fail if not a submit-based transaction */
493  if (false == hDevice->bSubmitCalled) {
495  }
496 
497  /* return true when bus goes quiet */
498  if (I2C_BUSY) {
499  *pbCompletionState = false;
500  } else {
501  *pbCompletionState = true;
502  }
503 
504  return ADI_I2C_SUCCESS;
505 }
506 
519 ADI_I2C_RESULT adi_i2c_GetNumberOfDataProcessed (ADI_I2C_HANDLE const hDevice, uint32_t *pDataCount) {
520 
521 #ifdef ADI_DEBUG
522  if (IsDeviceHandle(hDevice)) {
524  }
525 #endif
526 
527  *pDataCount = hDevice->nBytesProcessed;
528 
529  return ADI_I2C_SUCCESS;
530 }
531 
567 ADI_I2C_RESULT adi_i2c_GetBuffer (ADI_I2C_HANDLE const hDevice, uint32_t* const pHwErrors) {
568 
569 #ifdef ADI_DEBUG
570  if (IsDeviceHandle(hDevice)) {
572  }
573 #endif
574 
575  /* fail if not a submit-based transaction */
576  if (false == hDevice->bSubmitCalled) {
578  }
579 
580  /* block until complete or error interrupt sets the semaphore */
581  SEM_PEND(hDevice, ADI_I2C_SEMAPHORE_FAILED);
582 
583  /* delay until bus goes quiet */
584  while (I2C_BUSY) {
585  ;
586  }
587 
588  /* copy out any hardware errors... */
589  *pHwErrors = hDevice->hwErrors;
590  if (0u != hDevice->hwErrors) {
591  /* set the HW error return code */
592  hDevice->result = ADI_I2C_HW_ERROR_DETECTED;
593  }
594 
595  /* return transaction result code */
596  return hDevice->result;
597 }
598 
599 
610 ADI_I2C_RESULT adi_i2c_GetHWMaskedErrors (ADI_I2C_HANDLE const hDevice, uint16_t *pHwMaskedErrors) {
611 
612 #ifdef ADI_DEBUG
613  if (IsDeviceHandle(hDevice)) {
615  }
616 #endif
617 
618  *pHwMaskedErrors = hDevice->hwMaskedErrors;
619 
620  return ADI_I2C_SUCCESS;
621 }
622 
635 
636 #ifdef ADI_DEBUG
637  if (IsDeviceHandle(hDevice)) {
639  }
640 #endif
641 
642  /* destroy/recreate the semaphore to force a clear state */
643  SEM_DELETE(hDevice, ADI_I2C_SEMAPHORE_FAILED)
644  ;
645  SEM_CREATE(hDevice, "i2c_sem", ADI_I2C_SEMAPHORE_FAILED)
646  ;
647 
648  /* reset the driver and HW state */
649  return i2cReset(hDevice);
650 }
651 
676 ADI_I2C_RESULT adi_i2c_SetBitRate (ADI_I2C_HANDLE const hDevice, uint32_t const requestedBitRate32) {
677 
678  uint32_t clockFrequency32, halfClock32;
679  uint16_t halfClock16;
680  uint16_t highTime16, lowTime16;
681 
682 #ifdef ADI_DEBUG
683  if (IsDeviceHandle(hDevice)) {
685  }
686  if (I2C_BUSY) {
687  return ADI_I2C_DEVICE_IN_USE;
688  }
689 #endif
690 
691  /* get input clockrate from power service */
692  if (ADI_PWR_SUCCESS != adi_pwr_GetClockFrequency(ADI_CLOCK_PCLK, &clockFrequency32)) {
693  return ADI_I2C_BAD_SYS_CLOCK;
694  }
695 
696  /* block requests above max rated 400kHz operation */
697  if (ADI_I2C_MAX_RATE < requestedBitRate32) {
698  return ADI_I2C_BAD_BITRATE;
699  }
700 
701  /* compute half-cycle period in 32-bits (">>1" is divide by 2) */
702  halfClock32 = (clockFrequency32 / requestedBitRate32) >> 1; /* HRM equation */
703 
704  /* downcast to 16-bit to match destination field */
705  halfClock16 = (uint16_t)(halfClock32 & 0x0000ffffu);
706 
707  /* check for lost precision in conversion */
708  if (halfClock32 != halfClock16) {
709  return ADI_I2C_BAD_BITRATE;
710  }
711 
712  /* adjust high and low durations per HRM */
713  highTime16 = halfClock16 - 7u; /* empirical: varies with board layout, pullups, etc */
714  lowTime16 = halfClock16 - 1u;
715 
716  /* shift values into their clock rate divider register positions */
717  highTime16 <<= BITP_I2C_DIV_HIGH;
718  lowTime16 <<= BITP_I2C_DIV_LOW;
719 
720  /* check for divider overflows beyond designated (8-bit) field masks */
721  if ( (uZero16 != ((uint16_t)highTime16 & (uint16_t)(~(BITM_I2C_DIV_HIGH))))
722  ||
723  (uZero16 != ((uint16_t)lowTime16 & (uint16_t)(~(BITM_I2C_DIV_LOW))))
724  ) {
725  return ADI_I2C_BAD_BITRATE;
726  }
727 
728  /* program new values */
729  hDevice->pDev->DIV = highTime16 | lowTime16;
730 
731  return ADI_I2C_SUCCESS;
732 }
733 
734 
755 ADI_I2C_RESULT adi_i2c_SetSlaveAddress (ADI_I2C_HANDLE const hDevice, uint16_t const SlaveAddress) {
756 
757 #ifdef ADI_DEBUG
758  if (IsDeviceHandle(hDevice)) {
760  }
761  if (I2C_BUSY) {
762  return ADI_I2C_DEVICE_IN_USE;
763  }
764 #endif
765 
766  /* verify no slave address bits fall outside the 7-bit addressing model (10-bit addressing not supported) */
767  if (uZero16 != (SlaveAddress & (uint16_t)(~(BITM_I2C_ADDR1_VALUE >> 1)))) {
769  }
770 
771  /* save new address */
772  hDevice->i2cDeviceAddress = SlaveAddress;
773 
774  return ADI_I2C_SUCCESS;
775 }
776 
789 
790 #ifdef ADI_DEBUG
791  if (IsDeviceHandle(hDevice)) {
793  }
794  if (eMaskedErrors > ( ADI_I2C_HW_ERROR_NACK_ADDR \
801  }
802 #endif
803 
804  hDevice->hwMaskedErrors = eMaskedErrors;
805 
806  return ADI_I2C_SUCCESS;
807 }
808 
809 
841 ADI_I2C_RESULT adi_i2c_IssueGeneralCall (ADI_I2C_HANDLE const hDevice, uint8_t* const pData, uint8_t const nDataSize, uint32_t* const pHwErrors) {
842 
843  ADI_I2C_RESULT result;
845 
846 #ifdef ADI_DEBUG
847  if (IsDeviceHandle(hDevice)) {
849  }
850  if (I2C_BUSY) {
851  return ADI_I2C_DEVICE_IN_USE;
852  }
853 #endif
854 
855  /* force general call reserved target address of zero */
856  uint16_t savedSlaveAddress = hDevice->i2cDeviceAddress;
857  hDevice->i2cDeviceAddress = 0u;
858 
859  /* setup the transfer */
860  xfr.pPrologue = NULL;
861  xfr.nPrologueSize = 0u;
862  xfr.pData = pData;
863  xfr.nDataSize = nDataSize;
864  xfr.bReadNotWrite = false;
865  xfr.bRepeatStart = false;
866 
867  /* dispatch as a blocking transmit call */
868  result = adi_i2c_ReadWrite(hDevice, &xfr, pHwErrors);
869 
870  /* always restore saved slave address */
871  hDevice->i2cDeviceAddress = savedSlaveAddress;
872 
873  if (ADI_I2C_SUCCESS != result) {
874  return result; /* read/write failure... */
875  } else {
876  return hDevice->result; /* actual result */
877  }
878 }
879 
880 
892 ADI_I2C_RESULT adi_i2c_SetBusClear (ADI_I2C_HANDLE const hDevice, const bool busClr, const bool stopBusClr) {
893 
894 #ifdef ADI_DEBUG
895  if (IsDeviceHandle(hDevice)) {
897  }
898 #endif
899 
900  uint16_t mctl = hDevice->pDev->MCTL;
901 
902  if (busClr) {
903  mctl |= BITM_I2C_MCTL_BUSCLR; /* set bit BUSCLR */
904  }else{
905  mctl &= (~BITM_I2C_MCTL_BUSCLR); /* clear bit BUSCLR */
906  }
907 
908  if (stopBusClr) {
909  mctl |= BITM_I2C_MCTL_STOPBUSCLR; /* set bit STOPBUSCLR */
910  }else{
911  mctl &= (~BITM_I2C_MCTL_STOPBUSCLR); /* clear bit STOPBUSCLR */
912  }
913 
914  hDevice->pDev->MCTL = mctl; /* update MCTL register */
915  return ADI_I2C_SUCCESS;
916 }
917 
918 
922 /**********************************************************************************\
923 |*****************************static helper functions******************************|
924 \**********************************************************************************/
925 
926 static void submitTransaction(ADI_I2C_HANDLE const hDevice, ADI_I2C_TRANSACTION* const pTransaction) {
927 
928  /* reset internal return code */
929  hDevice->result = ADI_I2C_SUCCESS;
930 
931  /* reset hardware error code */
932  hDevice->hwErrors = ADI_I2C_HW_ERROR_NONE;
933 
934  /* reset the number of received bytes. */
935  hDevice->nBytesProcessed = 0;
936 
937  /* wait for HW to be ready */
938  while (I2C_BUSY) {
939  ;
940  }
941 
942  /* save common user parameters */
943  hDevice->pNextPrologueByte = pTransaction->pPrologue;
944  hDevice->remainingPrologueCount = pTransaction->nPrologueSize;
945  hDevice->bRepeatStart = pTransaction->bRepeatStart;
946 
947  /* encode (mask and upshift) the slave address, leaving room for the r/w control bit (LSB) */
948  hDevice->i2cEncodedDeviceAddress = (hDevice->i2cDeviceAddress & (BITM_I2C_ADDR1_VALUE >> 1)) << 1;
949 
950  /* dispatch */
951  if (pTransaction->bReadNotWrite) {
952 
953  /* setup read parameters */
954  hDevice->pNextReadByte = pTransaction->pData;
955  hDevice->remainingReadCount = pTransaction->nDataSize;
956  hDevice->pNextWriteByte = NULL;
957  hDevice->remainingWriteCount = 0u;
958 
959  /* set read bit */
960  hDevice->i2cEncodedDeviceAddress |= READ_NOT_WRITE;
961 
962  /* commence receive */
963  commenceReceive(hDevice);
964 
965  } else {
966 
967  /* setup write parameters */
968  hDevice->pNextReadByte = NULL;
969  hDevice->remainingReadCount = 0u;
970  hDevice->pNextWriteByte = pTransaction->pData;
971  hDevice->remainingWriteCount = pTransaction->nDataSize;
972 
973  /* clear read bit */
974  hDevice->i2cEncodedDeviceAddress &= (~READ_NOT_WRITE);
975 
976  /* commence transmit */
977  commenceTransmit(hDevice);
978  }
979 }
980 
981 
982 static void commenceTransmit(ADI_I2C_HANDLE const hDevice) {
983 
984  /* transmit is always pure transmit, whether we have a prologue or not... */
985 
986  /* enable PIO interrupts */
987  NVIC_EnableIRQ(hDevice->pDevInfo->pioIRQn);
988 
989  /* enable i2c for PIO-based transmit interrupts */
990  hDevice->pDev->MCTL |= (BITM_I2C_MCTL_IENMTX | BITM_I2C_MCTL_MASEN);
991 
992  /* how many bytes are available in the transmit FIFO (2-deep) */
993  uint16_t writableBytes = 2u - ((hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MTXF) >> BITP_I2C_STAT_MTXF);
994 
995  /* prime transmit FIFO with any prologue data */
996  while ((hDevice->remainingPrologueCount) && (0u < writableBytes)) {
997  hDevice->pDev->MTX = *hDevice->pNextPrologueByte;
998  hDevice->pNextPrologueByte++;
999  hDevice->remainingPrologueCount--;
1000  writableBytes--;
1001  }
1002 
1003  /* flesh out any remaining FIFO space with transmit data */
1004  while ((hDevice->remainingWriteCount) && (0u < writableBytes) ) {
1005  hDevice->pDev->MTX = *hDevice->pNextWriteByte;
1006  hDevice->pNextWriteByte++;
1007  hDevice->remainingWriteCount--;
1008  hDevice->nBytesProcessed++;
1009  writableBytes--;
1010  }
1011 
1012  /* launch the transmit */
1013  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
1014 }
1015 
1016 
1017 /* initiate receive addressing phase */
1018 static void commenceReceive(ADI_I2C_HANDLE const hDevice) {
1019 
1020  /* receive can be either pure receive (no prologue),
1021  or a transmit (of prologue) followed by a receive */
1022 
1023  /* enable PIO interrupts */
1024  NVIC_EnableIRQ(hDevice->pDevInfo->pioIRQn);
1025 
1026  /* enable i2c for PIO-based receive interrupts */
1027  hDevice->pDev->MCTL |= (uint16_t)(BITM_I2C_MCTL_IENMRX | BITM_I2C_MCTL_MASEN);
1028 
1029  /* program HW receive count */
1030  if (hDevice->remainingReadCount > BITM_I2C_MRXCNT_EXTEND) {
1031  hDevice->pDev->MRXCNT = BITM_I2C_MRXCNT_EXTEND;
1032  hDevice->remainingReadCount -= BITM_I2C_MRXCNT_EXTEND;
1033  } else {
1034  hDevice->pDev->MRXCNT = hDevice->remainingReadCount - 1u;
1035  hDevice->remainingReadCount = 0u;
1036  }
1037 
1038  /* if we have prologue (the dreaded "COMBINED FORMAT"), transmit the prologue prior to data receive... */
1039  if (hDevice->remainingPrologueCount) {
1040 
1041  /* -OR- in transmit interrupt enable if we have prologue data to send */
1042  hDevice->pDev->MCTL |= BITM_I2C_MCTL_IENMTX;
1043 
1044  /* how many bytes are available in the transmit FIFO (should be 2) */
1045  uint16_t writableBytes = 2u - ((hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MTXF) >> BITP_I2C_STAT_MTXF);
1046 
1047  /* prime transmit FIFO with any prologue data (memory address or command) first */
1048  while ((hDevice->remainingPrologueCount) && (0u < writableBytes)) {
1049  hDevice->pDev->MTX = *hDevice->pNextPrologueByte;
1050  hDevice->pNextPrologueByte++;
1051  hDevice->remainingPrologueCount--;
1052  writableBytes--;
1053  }
1054 
1055  /* initiate prologue transmit with read bit cleared (for prologue write) */
1056  /* (read sequence is initiated by transmit handler, *after* prologue is transmitted...) */
1057  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress & (uint16_t)(~READ_NOT_WRITE);
1058 
1059  } else {
1060 
1061  /* no prologue... initiate pure receive (read bit already set) */
1062  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
1063  }
1064 }
1065 
1066 
1067 /* reset the I2C HW */
1068 static ADI_I2C_RESULT i2cReset(ADI_I2C_HANDLE const hDevice) {
1069 
1070  volatile uint16_t temp;
1071  /* disable interrupts */
1072  NVIC_DisableIRQ(hDevice->pDevInfo->pioIRQn);
1073 
1074  /* reset any pending interrupts and TX FIFO (W1C) */
1075  temp = hDevice->pDev->MSTAT;
1076  hDevice->pDev->MSTAT = temp;
1077 
1078  /* discard any rogue RX FIFO data */
1079  while (uZero16 != (hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MRXF)) {
1080  volatile uint16_t delme ADI_UNUSED_ATTRIBUTE = hDevice->pDev->MTX;
1081  }
1082 
1083  /* reset i2c control register */
1084  hDevice->pDev->MCTL = 0u;
1085 
1086  /* reset repeat start logic */
1087  hDevice->pDev->SHCTL = 1u;
1088 
1089  /* (re)assert controller defaults from user config values */
1090  hDevice->pDev->MCTL = hDevice->pDevInfo->pConfig->MasterControlRegister;
1091  hDevice->pDev->DIV = hDevice->pDevInfo->pConfig->ClockDividerRegister;
1092  hDevice->pDev->SHCTL = hDevice->pDevInfo->pConfig->SharedControlRegister;
1093  hDevice->pDev->TCTL = hDevice->pDevInfo->pConfig->TimingControlRegister;
1094  hDevice->pDev->ASTRETCH_SCL = hDevice->pDevInfo->pConfig->ClockStretchRegister;
1095  hDevice->i2cDeviceAddress = hDevice->pDevInfo->pConfig->TargetSlaveAddress;
1096 
1097  return ADI_I2C_SUCCESS;
1098 }
1099 
1100 
1101 /**********************************************************************************\
1102 |********************************interrupt handlers********************************|
1103 \**********************************************************************************/
1104 
1105 
1106 /* transmit interrupt handler */
1107 static void transmitHandler(ADI_I2C_HANDLE const hDevice) {
1108 
1109  /* how much room in transmit FIFO? */
1110  /* DO ***NOT*** USE MSTAT:MTXF... FALSELY INDICATES MOSTLY FULL FIFO! */
1111  uint16_t writableBytes = 2u - ((hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MTXF) >> BITP_I2C_STAT_MTXF);
1112 
1113  /* for extended prologues, continue pushing prologue data out */
1114  while ((hDevice->remainingPrologueCount) && (0u < writableBytes)) {
1115  hDevice->pDev->MTX = *hDevice->pNextPrologueByte;
1116  hDevice->pNextPrologueByte++;
1117  hDevice->remainingPrologueCount--;
1118  writableBytes--;
1119  }
1120 
1121  /* once the prologue is done... */
1122  if (0u == hDevice->remainingPrologueCount) {
1123 
1124  /* if we have a completed prologue associated with a read sequence... */
1125  if (0u < hDevice->remainingReadCount) {
1126 
1127  /* initiate the read (subsequently driven by receive interrupt handler) */
1128  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
1129 
1130  } else {
1131 
1132  /* normal transmit interrupt: just push transmit data */
1133  while ((hDevice->remainingWriteCount) && (0u < writableBytes)) {
1134  hDevice->pDev->MTX = *hDevice->pNextWriteByte;
1135  hDevice->pNextWriteByte++;
1136  hDevice->remainingWriteCount--;
1137  hDevice->nBytesProcessed++;
1138  writableBytes--;
1139  }
1140  }
1141  }
1142 
1148  if ((0u == hDevice->remainingPrologueCount) && (0 == hDevice->remainingWriteCount)) {
1149  const uint16_t bit_IENMTX = (uint16_t) BITM_I2C_MCTL_IENMTX;
1150  const uint16_t mctl = hDevice->pDev->MCTL & ~bit_IENMTX;
1151  hDevice->pDev->MCTL = mctl;
1152  }
1153 
1154  /* clear TX interrupt as we complete transmit writes */
1155  if (0u == hDevice->remainingWriteCount) {
1156  hDevice->pDev->MSTAT = BITM_I2C_MSTAT_MTXREQ;
1157  }
1158 }
1159 
1160 
1161 /* receive interrupt handler */
1162 static void receiveHandler(ADI_I2C_HANDLE const hDevice) {
1163 
1164  /* note: we never need to deal with prologue data here... it will already be transmitted... */
1165  /* how many bytes in receive FIFO? */
1166  uint16_t readableBytes = (hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MRXF) >> BITP_I2C_STAT_MRXF;
1167 
1168  /* pull bytes from fifo */
1169  while (0u < readableBytes) {
1170 
1171  readableBytes--;
1172  hDevice->nBytesProcessed++;
1173 
1174  /* pull one byte */
1175  *hDevice->pNextReadByte = (uint8_t)hDevice->pDev->MRX;
1176  hDevice->pNextReadByte++;
1177 
1178  if (0u == hDevice->pDev->MCRXCNT) {
1179 
1180  /* if HW read counter goes to zero with remaining data to read, reprogram read count */
1181  if (hDevice->remainingReadCount > BITM_I2C_MRXCNT_EXTEND) {
1182  /* use extended count flag for large remaining counts... */
1183  hDevice->pDev->MRXCNT = BITM_I2C_MRXCNT_EXTEND;
1184  hDevice->remainingReadCount -= BITM_I2C_MRXCNT_EXTEND;
1185  } else {
1186  if (hDevice->remainingReadCount) {
1187  /* new count fits... no need for extended count */
1188  hDevice->pDev->MRXCNT = hDevice->remainingReadCount - 1u;
1189  hDevice->remainingReadCount = 0u;
1190  }
1191  }
1192  }
1193  }
1194 }
1195 
1196 /* completion interrupt handler */
1197 static void completeHandler(ADI_I2C_HANDLE const hDevice) {
1198 
1199  /* block on busy until all transmit data has both left
1200  the fifo AND has been fully serialized to the bus. */
1201  while (I2C_BUSY) {
1202  ;
1203  }
1204 
1205  /* disable interrupts */
1206  NVIC_DisableIRQ(hDevice->pDevInfo->pioIRQn);
1207 
1208  /* reset controller to default user config state */
1209  hDevice->pDev->MCTL = (uint16_t)gConfigInfo->MasterControlRegister;
1210 }
1211 
1212 
1213 /* error interrupt handler */
1214 static void errorHandler(ADI_I2C_HANDLE const hDevice) {
1215 
1216  /* accumulate I2C bus errors */
1217 
1218  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_NACKADDR)) {
1219  hDevice->hwErrors |= ADI_I2C_HW_ERROR_NACK_ADDR;
1220  }
1221 
1222  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_NACKDATA)) {
1223  hDevice->hwErrors |= ADI_I2C_HW_ERROR_NACK_DATA;
1224  }
1225 
1226  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_ALOST)) {
1227  hDevice->hwErrors |= ADI_I2C_HW_ERROR_ARBITRATION_LOST;
1228  }
1229 
1230  if (uZero16 != (hDevice->hwStatus & (uint16_t) BITM_I2C_MSTAT_MRXOVR)) {
1231  hDevice->hwErrors |= ADI_I2C_HW_ERROR_MRXOVR;
1232  }
1233 
1234  if (uZero16 != (hDevice->hwStatus & (uint16_t) BITM_I2C_MSTAT_MTXUNDR)) {
1235  hDevice->hwErrors |= ADI_I2C_HW_ERROR_MTXUNDR;
1236  }
1237 
1238  /* Mask out errors as configured in adi_SetHWMaskedErrors. */
1239  hDevice->hwErrors &= ~hDevice->hwMaskedErrors;
1240 
1241  /* if no other errors exist or were masked, note we had an unexpected error */
1242  if ((hDevice->hwErrors == ADI_I2C_HW_ERROR_NONE) && (uZero16 == hDevice->hwMaskedErrors)) {
1243  hDevice->hwErrors = ADI_I2C_HW_ERROR_UNEXPECTED_ERROR;
1244  }
1245 
1246 }
1247 
1248 
1249 /**********************************************************************************\
1250 |*****************************I2C INTERRUPT HANDLER********************************|
1251 \**********************************************************************************/
1252 
1253 
1254 /* PIO mode I2C interrupt handler */
1255 void I2C0_Master_Int_Handler(void) {
1256 
1257  /* rtos prologue */
1258  ISR_PROLOG()
1259  ;
1260 
1261  /* recover device handle */
1262  ADI_I2C_HANDLE const hDevice = (ADI_I2C_HANDLE)i2c_device_info[0].hDevice;
1263 
1264  /* save destructive status read... */
1265  hDevice->hwStatus = hDevice->pDev->MSTAT;
1266 
1267  /* if RepeatStart request is pending, rewrite address register ASAP (and only once) to block stop bit */
1268  if (hDevice->bRepeatStart) {
1269  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
1270  hDevice->bRepeatStart = false; /* just do it once on 1st interrupt */
1271  }
1272 
1273  /* forward TX interrupts to TX handler */
1274  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_MTXREQ)) {
1275  transmitHandler(hDevice);
1276  }
1277 
1278  /* forward RX interrupts to RX handler */
1279  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_MRXREQ)) {
1280  receiveHandler(hDevice);
1281  }
1282 
1283  /* dispatch any errors */
1284  if (uZero16 != (hDevice->hwStatus & ADI_I2C_STATUS_ERROR_MASK)) {
1285  errorHandler(hDevice);
1286  }
1287 
1288  /* transmit complete */
1289  if (uZero16 != (hDevice->hwStatus & BITM_I2C_MSTAT_TCOMP)) {
1290  completeHandler(hDevice);
1291 
1292  /* post on completion */
1293  SEM_POST(hDevice);
1294  }
1295 
1296  /* rtos epilogue */
1297  ISR_EPILOG()
1298  ;
1299 }
1300 
1304 /* @} */
ADI_I2C_RESULT adi_i2c_IssueGeneralCall(ADI_I2C_HANDLE const hDevice, uint8_t *const pData, uint8_t const nDataSize, uint32_t *const pHwErrors)
Transmit a General Call command to all slave devices on the I2C bus.
Definition: adi_i2c.c:841
uint8_t * pPrologue
Definition: adi_i2c.h:170
ADI_I2C_RESULT adi_i2c_Open(uint32_t const DeviceNum, void *const pMemory, uint32_t const MemorySize, ADI_I2C_HANDLE *const phDevice)
Initialize and allocate an I2C device for use in Master Mode.
Definition: adi_i2c.c:151
ADI_I2C_RESULT adi_i2c_ReadWrite(ADI_I2C_HANDLE const hDevice, ADI_I2C_TRANSACTION *const pTransaction, uint32_t *const pHwErrors)
Blocking I2C Master-Mode data read/write API.
Definition: adi_i2c.c:325
ADI_I2C_RESULT adi_i2c_IsBufferAvailable(ADI_I2C_HANDLE const hDevice, bool *const pbCompletionState)
Query if a non-blocking I2C transfer is complete.
Definition: adi_i2c.c:484
#define ADI_I2C_MEMORY_SIZE
Definition: adi_i2c.h:104
uint16_t nDataSize
Definition: adi_i2c.h:173
ADI_I2C_RESULT adi_i2c_SetBusClear(ADI_I2C_HANDLE const hDevice, const bool busClr, const bool stopBusClr)
Assign BUSCLR and STOPBUSCLR bit values.
Definition: adi_i2c.c:892
ADI_I2C_RESULT adi_i2c_GetHWMaskedErrors(ADI_I2C_HANDLE const hDevice, uint16_t *pHwMaskedErrors)
Get the errors that have been masked out.
Definition: adi_i2c.c:610
struct __ADI_I2C_DEV_DATA_TYPE * ADI_I2C_HANDLE
Definition: adi_i2c.h:97
ADI_I2C_HW_ERRORS
Definition: adi_i2c.h:84
ADI_I2C_RESULT adi_i2c_SetBitRate(ADI_I2C_HANDLE const hDevice, uint32_t const requestedBitRate32)
Set the I2C serial bus speed.
Definition: adi_i2c.c:676
ADI_I2C_RESULT adi_i2c_Reset(ADI_I2C_HANDLE const hDevice)
Reset an I2C device and driver instance.
Definition: adi_i2c.c:634
ADI_PWR_RESULT adi_pwr_GetClockFrequency(const ADI_CLOCK_ID eClockId, uint32_t *pClock)
Get the frequency of the given clock. Obtain individual peripheral clock frequencies.
Definition: adi_pwr.c:435
uint8_t * pData
Definition: adi_i2c.h:172
ADI_I2C_RESULT adi_i2c_GetNumberOfDataProcessed(ADI_I2C_HANDLE const hDevice, uint32_t *pDataCount)
Get the number of data written into MTX or read from MRX following the transmission/reception of a tr...
Definition: adi_i2c.c:519
ADI_I2C_RESULT adi_i2c_SetHWMaskedErrors(ADI_I2C_HANDLE const hDevice, ADI_I2C_HW_ERRORS eMaskedErrors)
Mask out errors. Errors will not be reported.
Definition: adi_i2c.c:788
ADI_I2C_RESULT adi_i2c_SetSlaveAddress(ADI_I2C_HANDLE const hDevice, uint16_t const SlaveAddress)
Set the I2C serial bus slave address.
Definition: adi_i2c.c:755
ADI_I2C_RESULT adi_i2c_SubmitBuffer(ADI_I2C_HANDLE const hDevice, ADI_I2C_TRANSACTION *const pTransaction)
Non-Blocking I2C Master-Mode data read or data write API.
Definition: adi_i2c.c:423
ADI_I2C_RESULT
Definition: adi_i2c.h:55
#define ADI_I2C_MAX_RATE
Definition: adi_i2c.h:180
uint16_t nPrologueSize
Definition: adi_i2c.h:171
ADI_I2C_RESULT adi_i2c_Close(ADI_I2C_HANDLE const hDevice)
Uninitialize and deallocate an I2C device.
Definition: adi_i2c.c:248
ADI_I2C_RESULT adi_i2c_GetBuffer(ADI_I2C_HANDLE const hDevice, uint32_t *const pHwErrors)
Request ownership of a submitted buffer.
Definition: adi_i2c.c:567