ADuCM302x Device Drivers API Reference Manual  Release 3.1.2.0
adi_i2c.c
1 
59 #include <adi_processor.h>
60 #include <assert.h>
61 #include <string.h> /* for "memset" */
64 #include <drivers/general/adi_drivers_general.h>
65 #include <drivers/i2c/adi_i2c.h>
66 
69 #include <drivers/pwr/adi_pwr.h>
70 
71 #ifdef __ICCARM__
72 /*
73 * IAR MISRA C 2004 error suppressions.
74 *
75 *
76 * Pm011 (rule 6.3): Types which specify sign and size should be used
77 * We use bool which is accepted by MISRA but the toolchain does not accept it
78 *
79 * Pm123 (rule 8.5): there shall be no definition of objects or functions in a header file
80 * It is used in the _data.h file which isn't a header as such.
81 *
82 * Pm073 (rule 14.7): a function should have a single point of exit
83 * Pm143 (rule 14.7): a function should have a single point of exit at the end of the function
84 * Multiple returns are used for error handling.
85 *
86 * Pm088 (rule 17.4): pointer arithmetic should not be used.
87 * Relying on pointer arithmetic for buffer handling.
88 *
89 * Pm140 (rule 11.3): a cast should not be performed between a pointer type and an integral type
90 * The rule makes an exception for memory-mapped register accesses.
91 */
92 
93 #pragma diag_suppress=Pm011,Pm123,Pm073,Pm143,Pm088,Pm140
94 #endif /* __ICCARM__ */
95 
96 /* pull in internal data structures */
97 #include "adi_i2c_data.c"
98 
99 
100 /* handy type-safe zero */
101 uint16_t uZero16 = 0u;
102 
103 /* central busy checker */
104 #define I2C_BUSY (uZero16 != ((hDevice->pDev->MSTAT) & (uint16_t)(BITM_I2C_MSTAT_MBUSY | BITM_I2C_MSTAT_LINEBUSY)))
105 
109  #define READ_NOT_WRITE (1u)
110 
111 /* Override "weak" default binding in startup.c */
113 extern void I2C0_Master_Int_Handler(void);
114 
115 /* DS4 and DS5 bits of GPIO Port 0 drive strength select register */
116 #define I2C_GPIO_PORT0_DS4 ((uint16_t) ((uint16_t) 1<<4))
117 #define I2C_GPIO_PORT0_DS5 ((uint16_t) ((uint16_t) 1<<5))
118 
119 #define ADI_ADUCM302X_CHIPID_SI_1_2 0x284u
120 
122 #if defined(ADI_DEBUG)
123 /*
124  * Verifies a pointer to a driver points to one of the driver
125  * struct's internal to this file.
126  */
127 static bool IsDeviceHandle(ADI_I2C_HANDLE const hDevice);
128 static bool IsDeviceHandle(ADI_I2C_HANDLE const hDevice)
129 {
130  if ((i2c_device_info[0].hDevice != (hDevice)) && ((hDevice)->pDevInfo->hDevice != NULL)) {
131  return true;
132  } else {
133  return false;
134  }
135 }
136 #endif
137 
138 #if defined(__ADUCM302x__)
139 static ADI_SYS_REGISTERS adi_sys_base = { pADI_SYS };
140 #endif
141 
145 /**********************************************************************************\
146 |**********************************USER INTERFACE**********************************|
147 \**********************************************************************************/
148 
149 
181 ADI_I2C_RESULT adi_i2c_Open (uint32_t const DeviceNum, void* const pMemory, uint32_t const MemorySize, ADI_I2C_HANDLE* const phDevice) {
182 
183  /* make a device handle out of the user memory */
184  ADI_I2C_HANDLE hDevice = (ADI_I2C_HANDLE)pMemory;
185  #if defined(__ADUCM302x__)
186  /*
187  * I2C fix for Silicon Version 1.2
188  * Enable the drive strength of GPIO pins used for I2C communication.
189  */
190 
191  /* Get the pointer to the internal structure for System registers*/
192  ADI_SYS_REGISTERS *sys = &adi_sys_base;
193 
194  if( sys->pReg->CHIPID == ADI_ADUCM302X_CHIPID_SI_1_2 )
195  {
196  *((volatile uint32_t *)REG_GPIO0_DS) |= ( I2C_GPIO_PORT0_DS4 | I2C_GPIO_PORT0_DS5 );
197  }
198 
199  #endif
200 #if defined(ADI_DEBUG)
201  /* check requested device number */
202  if (DeviceNum >= (uint32_t)ADI_I2C_NUM_INSTANCES) {
204  }
205 
206  /* verify device is not already open */
207  if (i2c_device_info[DeviceNum].hDevice != NULL) {
208  return ADI_I2C_DEVICE_IN_USE;
209  }
210 
211  /* verify memory size macro value */
212  assert(ADI_I2C_MEMORY_SIZE == sizeof(ADI_I2C_DEV_DATA_TYPE));
213 
214  /* verify user-provided memory meets requirement */
215  if ((NULL == pMemory) || (MemorySize < (uint32_t)ADI_I2C_MEMORY_SIZE)) {
217  }
218 #endif
219 
220  /* store a bad handle in case of failure */
221  *phDevice = NULL;
222 
223  /*
224  * Link user memory (handle) to ADI_I2C_DEVICE_INFO data structure.
225  *
226  * ADI_I2C_DEVICE_INFO <==> ADI_I2C_HANDLE
227  *
228  * Clear the ADI_I2C_HANDLE memory. This also sets all bool
229  * structure members to false so we do not need to waste cycles
230  * setting these explicitly (e.g. hDevice->bRepearStart = false)
231  */
232  i2c_device_info[DeviceNum].hDevice = (ADI_I2C_DEV_DATA_TYPE *)pMemory;
233  memset(pMemory, 0, MemorySize);
234 
235  /* also link device handle within __ADI_I2C_DEV_DATA_TYPE data structure */
236  hDevice->pDevInfo = &i2c_device_info[DeviceNum];
237  /*
238  * Although the ADI_I2C_DEVICE_INFO struct has the physical device pointer
239  * for this instance, copying it to the ADI_I2C_HANDLE struct (in user memory)
240  * will minimize the runtime footprint and cycle count when accessing the I2C
241  * registers.
242  */
243  hDevice->pDev = i2c_device_info[DeviceNum].pDev;
244 
245  /* store a pointer to user's static configuration settings */
246  hDevice->pDevInfo->pConfig = (ADI_I2C_CONFIG*)&gConfigInfo[DeviceNum];
247 
248  /* create the semaphore */
249  SEM_CREATE(hDevice, "i2c_sem", ADI_I2C_SEMAPHORE_FAILED)
250  ;
251 
252  /* reset the driver and HW state */
253  ADI_I2C_RESULT ignore ADI_UNUSED_ATTRIBUTE = i2cReset(hDevice);
254 
255  /* store device handle into user handle */
256  *phDevice = (ADI_I2C_HANDLE)hDevice;
257 
258  return ADI_I2C_SUCCESS;
259 }
260 
261 
279 
280 #ifdef ADI_DEBUG
281  if (IsDeviceHandle(hDevice)) {
283  }
284 #endif
285 
286  /* destroy semaphore */
287  SEM_DELETE(hDevice,ADI_I2C_SEMAPHORE_FAILED)
288  ;
289 
290  /* reset the driver and HW state */
291  ADI_I2C_RESULT ignore ADI_UNUSED_ATTRIBUTE = i2cReset(hDevice);
292 
293  /* stub handle */
294  hDevice->pDevInfo->hDevice = NULL;
295 
296  return ADI_I2C_SUCCESS;
297 }
298 
299 
355 ADI_I2C_RESULT adi_i2c_ReadWrite (ADI_I2C_HANDLE const hDevice, ADI_I2C_TRANSACTION* const pTransaction, uint32_t* const pHwErrors) {
356 
357 #ifdef ADI_DEBUG
358  if (IsDeviceHandle(hDevice)) {
360  }
361  if (I2C_BUSY) {
362  return ADI_I2C_DEVICE_IN_USE;
363  }
364  /* NULL transaction data pointer or zero transaction data count */
365  if ((NULL == pTransaction->pData) || (0u == pTransaction->nDataSize)) {
367  }
368 #endif
369 
370  /* reset submit/get safeguard flag */
371  hDevice->bSubmitCalled = false;
372 
373  /* submit/commence the transaction */
374  submitTransaction(hDevice, pTransaction);
375 
376  /* block on internal transaction completion/error semaphore */
377  if (ADI_I2C_SUCCESS == hDevice->result) {
378 
379  SEM_PEND(hDevice, ADI_I2C_SEMAPHORE_FAILED);
380 
381  /* completion interrupt comes as FIFO unloads, but serialization may not be complete yet... */
382  /* must also wait for hardware busy status to clear before giving back control */
383  /* i.e., allow any transmit serialization to complete after last FIFO unload */
384  while (I2C_BUSY) {
385  ;
386  }
387  }
388 
389  /* copy out any hardware errors... */
390  *pHwErrors = hDevice->hwErrors;
391  if (0u != hDevice->hwErrors) {
392  /* set the HW error return code */
393  hDevice->result = ADI_I2C_HW_ERROR_DETECTED;
394  }
395 
396  /* return transaction result code */
397  return hDevice->result;
398 }
399 
400 
451 
452 #ifdef ADI_DEBUG
453  if (IsDeviceHandle(hDevice)) {
455  }
456  if (I2C_BUSY) {
457  return ADI_I2C_DEVICE_IN_USE;
458  }
459  /* NULL transaction data pointer or zero transaction data count */
460  if ((NULL == pTransaction->pData) || (0u == pTransaction->nDataSize)) {
462  }
463 #endif
464 
465  /* set submit/get safeguard flag */
466  hDevice->bSubmitCalled = true;
467 
468  /* submit/commence the transaction */
469  submitTransaction(hDevice, pTransaction);
470 
471  /* no blocking on submit... just return the submit result */
472  return hDevice->result;
473 }
474 
475 
511 ADI_I2C_RESULT adi_i2c_IsBufferAvailable (ADI_I2C_HANDLE const hDevice, bool* const pbCompletionState) {
512 
513 #ifdef ADI_DEBUG
514  if (IsDeviceHandle(hDevice)) {
516  }
517 #endif
518 
519  /* fail if not a submit-based transaction */
520  if (false == hDevice->bSubmitCalled) {
522  }
523 
524  /* return true when bus goes quiet */
525  if (I2C_BUSY) {
526  *pbCompletionState = false;
527  } else {
528  *pbCompletionState = true;
529  }
530 
531  return ADI_I2C_SUCCESS;
532 }
533 
534 
570 ADI_I2C_RESULT adi_i2c_GetBuffer (ADI_I2C_HANDLE const hDevice, uint32_t* const pHwErrors) {
571 
572 #ifdef ADI_DEBUG
573  if (IsDeviceHandle(hDevice)) {
575  }
576 #endif
577 
578  /* fail if not a submit-based transaction */
579  if (false == hDevice->bSubmitCalled) {
581  }
582 
583  /* block until complete or error interrupt sets the semaphore */
584  SEM_PEND(hDevice, ADI_I2C_SEMAPHORE_FAILED);
585 
586  /* delay until bus goes quiet */
587  while (I2C_BUSY) {
588  ;
589  }
590 
591  /* copy out any hardware errors... */
592  *pHwErrors = hDevice->hwErrors;
593  if (0u != hDevice->hwErrors) {
594  /* set the HW error return code */
595  hDevice->result = ADI_I2C_HW_ERROR_DETECTED;
596  }
597 
598  /* return transaction result code */
599  return hDevice->result;
600 }
601 
614 
615 #ifdef ADI_DEBUG
616  if (IsDeviceHandle(hDevice)) {
618  }
619 #endif
620 
621  /* destroy/recreate the semaphore to force a clear state */
622  SEM_DELETE(hDevice, ADI_I2C_SEMAPHORE_FAILED)
623  ;
624  SEM_CREATE(hDevice, "i2c_sem", ADI_I2C_SEMAPHORE_FAILED)
625  ;
626 
627  /* reset the driver and HW state */
628  return i2cReset(hDevice);
629 }
630 
631 
656 ADI_I2C_RESULT adi_i2c_SetBitRate (ADI_I2C_HANDLE const hDevice, uint32_t const requestedBitRate32) {
657 
658  uint32_t clockFrequency32, halfClock32;
659  uint16_t halfClock16;
660  uint16_t highTime16, lowTime16;
661 
662 #ifdef ADI_DEBUG
663  if (IsDeviceHandle(hDevice)) {
665  }
666  if (I2C_BUSY) {
667  return ADI_I2C_DEVICE_IN_USE;
668  }
669 #endif
670 
671  /* get input clockrate from power service */
672  if (ADI_PWR_SUCCESS != adi_pwr_GetClockFrequency(ADI_CLOCK_PCLK, &clockFrequency32)) {
673  return ADI_I2C_BAD_SYS_CLOCK;
674  }
675 
676  /* block requests above max rated 400kHz operation */
677  if (ADI_I2C_MAX_RATE < requestedBitRate32) {
678  return ADI_I2C_BAD_BITRATE;
679  }
680 
681  /* compute half-cycle period in 32-bits (">>1" is divide by 2) */
682  halfClock32 = (clockFrequency32 / requestedBitRate32) >> 1; /* HRM equation */
683 
684  /* downcast to 16-bit to match destination field */
685  halfClock16 = (uint16_t)(halfClock32 & 0x0000ffffu);
686 
687  /* check for lost precision in conversion */
688  if (halfClock32 != halfClock16) {
689  return ADI_I2C_BAD_BITRATE;
690  }
691 
692  /* adjust high and low durations per HRM */
693  highTime16 = halfClock16 - 7u; /* empirical: varies with board layout, pullups, etc */
694  lowTime16 = halfClock16 - 1u;
695 
696  /* shift values into their clock rate divider register positions */
697  highTime16 <<= BITP_I2C_DIV_HIGH;
698  lowTime16 <<= BITP_I2C_DIV_LOW;
699 
700  /* check for divider overflows beyond designated (8-bit) field masks */
701  if ( (uZero16 != ((uint16_t)highTime16 & (uint16_t)(~(BITM_I2C_DIV_HIGH))))
702  ||
703  (uZero16 != ((uint16_t)lowTime16 & (uint16_t)(~(BITM_I2C_DIV_LOW))))
704  ) {
705  return ADI_I2C_BAD_BITRATE;
706  }
707 
708  /* program new values */
709  hDevice->pDev->DIV = highTime16 | lowTime16;
710 
711  return ADI_I2C_SUCCESS;
712 }
713 
714 
735 ADI_I2C_RESULT adi_i2c_SetSlaveAddress (ADI_I2C_HANDLE const hDevice, uint16_t const SlaveAddress) {
736 
737 #ifdef ADI_DEBUG
738  if (IsDeviceHandle(hDevice)) {
740  }
741  if (I2C_BUSY) {
742  return ADI_I2C_DEVICE_IN_USE;
743  }
744 #endif
745 
746  /* verify no slave address bits fall outside the 7-bit addressing model (10-bit addressing not supported) */
747  if (uZero16 != (SlaveAddress & (uint16_t)(~(BITM_I2C_ADDR1_VALUE >> 1)))) {
749  }
750 
751  /* save new address */
752  hDevice->i2cDeviceAddress = SlaveAddress;
753 
754  return ADI_I2C_SUCCESS;
755 }
756 
757 
789 ADI_I2C_RESULT adi_i2c_IssueGeneralCall (ADI_I2C_HANDLE const hDevice, uint8_t* const pData, uint8_t const nDataSize, uint32_t* const pHwErrors) {
790 
791  ADI_I2C_RESULT result;
793 
794 #ifdef ADI_DEBUG
795  if (IsDeviceHandle(hDevice)) {
797  }
798  if (I2C_BUSY) {
799  return ADI_I2C_DEVICE_IN_USE;
800  }
801 #endif
802 
803  /* force general call reserved target address of zero */
804  uint16_t savedSlaveAddress = hDevice->i2cDeviceAddress;
805  hDevice->i2cDeviceAddress = 0u;
806 
807  /* setup the transfer */
808  xfr.pPrologue = NULL;
809  xfr.nPrologueSize = 0u;
810  xfr.pData = pData;
811  xfr.nDataSize = nDataSize;
812  xfr.bReadNotWrite = false;
813  xfr.bRepeatStart = false;
814 
815  /* dispatch as a blocking transmit call */
816  result = adi_i2c_ReadWrite(hDevice, &xfr, pHwErrors);
817 
818  /* always restore saved slave address */
819  hDevice->i2cDeviceAddress = savedSlaveAddress;
820 
821  if (ADI_I2C_SUCCESS != result) {
822  return result; /* read/write failure... */
823  } else {
824  return hDevice->result; /* actual result */
825  }
826 }
827 
828 
832 /**********************************************************************************\
833 |*****************************static helper functions******************************|
834 \**********************************************************************************/
835 
836 static void submitTransaction(ADI_I2C_HANDLE const hDevice, ADI_I2C_TRANSACTION* const pTransaction) {
837 
838  /* reset internal return code */
839  hDevice->result = ADI_I2C_SUCCESS;
840 
841  /* reset hardware error code */
842  hDevice->hwErrors = ADI_I2C_HW_ERROR_NONE;
843 
844  /* wait for HW to be ready */
845  while (I2C_BUSY) {
846  ;
847  }
848 
849  /* save common user parameters */
850  hDevice->pNextPrologueByte = pTransaction->pPrologue;
851  hDevice->remainingPrologueCount = pTransaction->nPrologueSize;
852  hDevice->bRepeatStart = pTransaction->bRepeatStart;
853 
854  /* encode (mask and upshift) the slave address, leaving room for the r/w control bit (LSB) */
855  hDevice->i2cEncodedDeviceAddress = (hDevice->i2cDeviceAddress & (BITM_I2C_ADDR1_VALUE >> 1)) << 1;
856 
857  /* dispatch */
858  if (pTransaction->bReadNotWrite) {
859 
860  /* setup read parameters */
861  hDevice->pNextReadByte = pTransaction->pData;
862  hDevice->remainingReadCount = pTransaction->nDataSize;
863  hDevice->pNextWriteByte = NULL;
864  hDevice->remainingWriteCount = 0u;
865 
866  /* set read bit */
867  hDevice->i2cEncodedDeviceAddress |= READ_NOT_WRITE;
868 
869  /* commence receive */
870  commenceReceive(hDevice);
871 
872  } else {
873 
874  /* setup write parameters */
875  hDevice->pNextReadByte = NULL;
876  hDevice->remainingReadCount = 0u;
877  hDevice->pNextWriteByte = pTransaction->pData;
878  hDevice->remainingWriteCount = pTransaction->nDataSize;
879 
880  /* clear read bit */
881  hDevice->i2cEncodedDeviceAddress &= (~READ_NOT_WRITE);
882 
883  /* commence transmit */
884  commenceTransmit(hDevice);
885  }
886 }
887 
888 
889 static void commenceTransmit(ADI_I2C_HANDLE const hDevice) {
890 
891  /* transmit is always pure transmit, whether we have a prologue or not... */
892 
893  /* enable PIO interrupts */
894  NVIC_EnableIRQ(hDevice->pDevInfo->pioIRQn);
895 
896  /* enable i2c for PIO-based transmit interrupts */
897  hDevice->pDev->MCTL |= (BITM_I2C_MCTL_IENMTX | BITM_I2C_MCTL_MASEN);
898 
899  /* how many bytes are available in the transmit FIFO (2-deep) */
900  uint16_t writableBytes = 2u - (hDevice->pDev->MSTAT & (uint16_t)BITM_I2C_MSTAT_MTXF);
901 
902  /* prime transmit FIFO with any prologue data */
903  while ((hDevice->remainingPrologueCount) && (0u < writableBytes)) {
904  hDevice->pDev->MTX = *hDevice->pNextPrologueByte;
905  hDevice->pNextPrologueByte++;
906  hDevice->remainingPrologueCount--;
907  writableBytes--;
908  }
909 
910  /* flesh out any remaining FIFO space with transmit data */
911  while ((hDevice->remainingWriteCount) && (0u < writableBytes) ) {
912  hDevice->pDev->MTX = *hDevice->pNextWriteByte;
913  hDevice->pNextWriteByte++;
914  hDevice->remainingWriteCount--;
915  writableBytes--;
916  }
917 
918  /* launch the transmit */
919  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
920 }
921 
922 
923 /* initiate receive addressing phase */
924 static void commenceReceive(ADI_I2C_HANDLE const hDevice) {
925 
926  /* receive can be either pure receive (no prologue),
927  or a transmit (of prologue) followed by a receive */
928 
929  /* enable PIO interrupts */
930  NVIC_EnableIRQ(hDevice->pDevInfo->pioIRQn);
931 
932  /* enable i2c for PIO-based receive interrupts */
933  hDevice->pDev->MCTL |= (uint16_t)(BITM_I2C_MCTL_IENMRX | BITM_I2C_MCTL_MASEN);
934 
935  /* program HW receive count */
936  if (hDevice->remainingReadCount > BITM_I2C_MRXCNT_EXTEND) {
937  hDevice->pDev->MRXCNT = BITM_I2C_MRXCNT_EXTEND;
938  hDevice->remainingReadCount -= BITM_I2C_MRXCNT_EXTEND;
939  } else {
940  hDevice->pDev->MRXCNT = hDevice->remainingReadCount - 1u;
941  hDevice->remainingReadCount = 0u;
942  }
943 
944  /* if we have prologue (the dreaded "COMBINED FORMAT"), transmit the prologue prior to data receive... */
945  if (hDevice->remainingPrologueCount) {
946 
947  /* -OR- in transmit interrupt enable if we have prologue data to send */
948  hDevice->pDev->MCTL |= BITM_I2C_MCTL_IENMTX;
949 
950  /* how many bytes are available in the transmit FIFO (should be 2) */
951  uint16_t writableBytes = 2u - (hDevice->pDev->MSTAT & (uint16_t)BITM_I2C_MSTAT_MTXF);
952 
953  /* prime transmit FIFO with any prologue data (memory address or command) first */
954  while ((hDevice->remainingPrologueCount) && (0u < writableBytes)) {
955  hDevice->pDev->MTX = *hDevice->pNextPrologueByte;
956  hDevice->pNextPrologueByte++;
957  hDevice->remainingPrologueCount--;
958  writableBytes--;
959  }
960 
961  /* initiate prologue transmit with read bit cleared (for prologue write) */
962  /* (read sequence is initiated by transmit handler, *after* prologue is transmitted...) */
963  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress & (uint16_t)(~READ_NOT_WRITE);
964 
965  } else {
966 
967  /* no prologue... initiate pure receive (read bit already set) */
968  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
969  }
970 }
971 
972 
973 /* reset the I2C HW */
974 static ADI_I2C_RESULT i2cReset(ADI_I2C_HANDLE const hDevice) {
975 
976  volatile uint16_t temp;
977  /* disable interrupts */
978  NVIC_DisableIRQ(hDevice->pDevInfo->pioIRQn);
979 
980  /* reset any pending interrupts and TX FIFO (W1C) */
981  temp = hDevice->pDev->MSTAT;
982  hDevice->pDev->MSTAT = temp;
983 
984  /* discard any rogue RX FIFO data */
985  while (uZero16 != (hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MRXF)) {
986  volatile uint16_t delme ADI_UNUSED_ATTRIBUTE = hDevice->pDev->MTX;
987  }
988 
989  /* reset i2c control register */
990  hDevice->pDev->MCTL = 0u;
991 
992  /* reset repeat start logic */
993  hDevice->pDev->SHCTL = 1u;
994 
995  /* (re)assert controller defaults from user config values */
996  hDevice->pDev->MCTL = hDevice->pDevInfo->pConfig->MasterControlRegister;
997  hDevice->pDev->DIV = hDevice->pDevInfo->pConfig->ClockDividerRegister;
998  hDevice->pDev->SHCTL = hDevice->pDevInfo->pConfig->SharedControlRegister;
999  hDevice->pDev->TCTL = hDevice->pDevInfo->pConfig->TimingControlRegister;
1000  hDevice->pDev->ASTRETCH_SCL = hDevice->pDevInfo->pConfig->ClockStretchRegister;
1001  hDevice->i2cDeviceAddress = hDevice->pDevInfo->pConfig->TargetSlaveAddress;
1002 
1003  return ADI_I2C_SUCCESS;
1004 }
1005 
1006 
1007 /**********************************************************************************\
1008 |********************************interrupt handlers********************************|
1009 \**********************************************************************************/
1010 
1011 
1012 /* transmit interrupt handler */
1013 static void transmitHandler(ADI_I2C_HANDLE const hDevice) {
1014 
1015  /* how much room in transmit FIFO? */
1016  /* DO ***NOT*** USE MSTAT:MTXF... FALSELY INDICATES MOSTLY FULL FIFO! */
1017  uint16_t writableBytes = 2u - ((hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MTXF) >> BITP_I2C_STAT_MTXF);
1018 
1019  /* for extended prologues, continue pushing prologue data out */
1020  while ((hDevice->remainingPrologueCount) && (0u < writableBytes)) {
1021  hDevice->pDev->MTX = *hDevice->pNextPrologueByte;
1022  hDevice->pNextPrologueByte++;
1023  hDevice->remainingPrologueCount--;
1024  writableBytes--;
1025  }
1026 
1027  /* once the prologue is done... */
1028  if (0u == hDevice->remainingPrologueCount) {
1029 
1030  /* if we have a completed prologue associated with a read sequence... */
1031  if (0u < hDevice->remainingReadCount) {
1032 
1033  /* initiate the read (subsequently driven by receive interrupt handler) */
1034  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
1035 
1036  } else {
1037 
1038  /* normal transmit interrupt: just push transmit data */
1039  while ((hDevice->remainingWriteCount) && (0u < writableBytes)) {
1040  hDevice->pDev->MTX = *hDevice->pNextWriteByte;
1041  hDevice->pNextWriteByte++;
1042  hDevice->remainingWriteCount--;
1043  writableBytes--;
1044  }
1045  }
1046  }
1047 
1048  /* clear TX interrupt as we complete transmit writes */
1049  if (0u == hDevice->remainingWriteCount) {
1050  hDevice->pDev->MSTAT = BITM_I2C_MSTAT_MTXREQ;
1051  }
1052 }
1053 
1054 
1055 /* receive interrupt handler */
1056 static void receiveHandler(ADI_I2C_HANDLE const hDevice) {
1057 
1058  /* note: we never need to deal with prologue data here... it will already be transmitted... */
1059 
1060  /* how many bytes in receive FIFO? */
1061  uint16_t readableBytes = (hDevice->pDev->STAT & (uint16_t)BITM_I2C_STAT_MRXF) >> BITP_I2C_STAT_MRXF;
1062 
1063  /* pull bytes from fifo */
1064  while (0u < readableBytes) {
1065 
1066  readableBytes--;
1067 
1068  /* pull one byte */
1069  *hDevice->pNextReadByte = (uint8_t)hDevice->pDev->MRX;
1070  hDevice->pNextReadByte++;
1071 
1072  if (0u == hDevice->pDev->MCRXCNT) {
1073 
1074  /* if HW read counter goes to zero with remaining data to read, reprogram read count */
1075  if (hDevice->remainingReadCount > BITM_I2C_MRXCNT_EXTEND) {
1076  /* use extended count flag for large remaining counts... */
1077  hDevice->pDev->MRXCNT = BITM_I2C_MRXCNT_EXTEND;
1078  hDevice->remainingReadCount -= BITM_I2C_MRXCNT_EXTEND;
1079  } else {
1080  if (hDevice->remainingReadCount) {
1081  /* new count fits... no need for extended count */
1082  hDevice->pDev->MRXCNT = hDevice->remainingReadCount - 1u;
1083  hDevice->remainingReadCount = 0u;
1084  }
1085  }
1086  }
1087  }
1088 }
1089 
1090 /* completion interrupt handler */
1091 static void completeHandler(ADI_I2C_HANDLE const hDevice) {
1092 
1093  /* block on busy until all transmit data has both left
1094  the fifo AND has been fully serialized to the bus. */
1095  while (I2C_BUSY) {
1096  ;
1097  }
1098 
1099  /* disable interrupts */
1100  NVIC_DisableIRQ(hDevice->pDevInfo->pioIRQn);
1101 
1102  /* reset controller to default user config state */
1103  hDevice->pDev->MCTL = (uint16_t)gConfigInfo->MasterControlRegister;
1104 }
1105 
1106 
1107 /* error interrupt handler */
1108 static void errorHandler(ADI_I2C_HANDLE const hDevice) {
1109 
1110  /* accumulate I2C bus errors */
1111 
1112  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_NACKADDR)) {
1113  hDevice->hwErrors |= ADI_I2C_HW_ERROR_NACK_ADDR;
1114  }
1115 
1116  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_NACKDATA)) {
1117  hDevice->hwErrors |= ADI_I2C_HW_ERROR_NACK_DATA;
1118  }
1119 
1120  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_ALOST)) {
1121  hDevice->hwErrors |= ADI_I2C_HW_ERROR_ARBITRATION_LOST;
1122  }
1123 
1124  /* if no other errors exist, note we had an unexpected error */
1125  if (hDevice->hwErrors == ADI_I2C_HW_ERROR_NONE) {
1126  hDevice->hwErrors = ADI_I2C_HW_ERROR_UNEXPECTED_ERROR;
1127  }
1128 }
1129 
1130 
1131 /**********************************************************************************\
1132 |*****************************I2C INTERRUPT HANDLER********************************|
1133 \**********************************************************************************/
1134 
1135 
1136 /* PIO mode I2C interrupt handler */
1137 void I2C0_Master_Int_Handler(void) {
1138 
1139  bool bPost = false;
1140 
1141  /* rtos prologue */
1142  ISR_PROLOG()
1143  ;
1144 
1145  /* recover device handle */
1146  ADI_I2C_HANDLE const hDevice = (ADI_I2C_HANDLE)i2c_device_info[0].hDevice;
1147 
1148  /* save destructive status read... */
1149  hDevice->hwStatus = hDevice->pDev->MSTAT;
1150 
1151  /* if RepeatStart request is pending, rewrite address register ASAP (and only once) to block stop bit */
1152  if (hDevice->bRepeatStart) {
1153  hDevice->pDev->ADDR1 = hDevice->i2cEncodedDeviceAddress;
1154  hDevice->bRepeatStart = false; /* just do it once on 1st interrupt */
1155  }
1156 
1157  /* forward TX interrupts to TX handler */
1158  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_MTXREQ)) {
1159  transmitHandler(hDevice);
1160  }
1161 
1162  /* forward RX interrupts to RX handler */
1163  if (uZero16 != (hDevice->hwStatus & (uint16_t)BITM_I2C_MSTAT_MRXREQ)) {
1164  receiveHandler(hDevice);
1165  }
1166 
1167  /* dispatch any errors */
1168  if (uZero16 != (hDevice->hwStatus & ADI_I2C_STATUS_ERROR_MASK)) {
1169  errorHandler(hDevice);
1170 
1171  /* post on bus error */
1172  bPost = true;
1173  }
1174 
1175  /* transmit complete */
1176  if (uZero16 != (hDevice->hwStatus & BITM_I2C_MSTAT_TCOMP)) {
1177  completeHandler(hDevice);
1178 
1179  /* post on completion */
1180  bPost = true;
1181  }
1182 
1183  /* just post once */
1184  if (true == bPost) {
1185  SEM_POST(hDevice);
1186  }
1187 
1188  /* rtos epilogue */
1189  ISR_EPILOG()
1190  ;
1191 }
1192 
1196 /* @} */
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:789
uint8_t * pPrologue
Definition: adi_i2c.h:200
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:181
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:355
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:511
#define ADI_I2C_MEMORY_SIZE
Definition: adi_i2c.h:134
uint16_t nDataSize
Definition: adi_i2c.h:203
struct __ADI_I2C_DEV_DATA_TYPE * ADI_I2C_HANDLE
Definition: adi_i2c.h:127
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:656
ADI_I2C_RESULT adi_i2c_Reset(ADI_I2C_HANDLE const hDevice)
Reset an I2C device and driver instance.
Definition: adi_i2c.c:613
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:467
uint8_t * pData
Definition: adi_i2c.h:202
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:735
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:450
ADI_I2C_RESULT
Definition: adi_i2c.h:86
#define ADI_I2C_MAX_RATE
Definition: adi_i2c.h:210
uint16_t nPrologueSize
Definition: adi_i2c.h:201
ADI_I2C_RESULT adi_i2c_Close(ADI_I2C_HANDLE const hDevice)
Uninitialize and deallocate an I2C device.
Definition: adi_i2c.c:278
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:570