ADICUP3029/AD5940 I2C issues

Dear Analog (),

I am using the AD5940_BIOZ-2Wire example with the evaluation board for AD5940 (+ADICUP3029). I am attempting to write I2C commands to an external GPIO expander, but the code gets stuck. 

Initially I set up an I2C handle inside AD5940Main.c as seen below:

  /* Setup I2C */
  /* device handle */
  ADI_I2C_HANDLE i2cDevice;
  //Dont use pinmux since i2c pins are already defined in adi_i2c_v1.c
  /* check set speed API */
  if(ADI_I2C_SUCCESS == adi_i2c_Open(0, ADI_I2C_MASTER, &devMem, ADI_I2C_MEMORY_SIZE, &i2cDevice)){
    printf("I2C Open");
  if(ADI_I2C_SUCCESS == adi_i2c_SetBitRate(i2cDevice, 400)){
    printf("I2C BitRate Set");  // top-end
  if(ADI_I2C_SUCCESS == adi_i2c_SetHardwareAddress(i2cDevice, 0x20)){
    printf("I2C Addr Set");

This code completes, but when I just after attempt to write on I2C using: adi_i2c_Write(i2cDevice, (unsigned char*)&Regs->Output, 1); this function gets stuck in I2C_BlockingIO() in adi_i2c_v1.c on this line:

/* Pend for the semaphore */

I don't know where this semaphore would've been defined earlier in the code since the only place I can find where it otherwise could've been defined is in adi_i2c_Open(), also in adi_i2c_v1.c:

/* create a semaphore for buffer management */

I don't have ADI_CFG_ENABLE_RTOS_SUPPORT defined in the IAR Linker. I've tried simply out-commenting the PEND_EVENT, after which the code runs, but no data is seen on SDA or SCL.

Any suggestions on solving the issue much appreciated!



Edited problem title to reflect updated problem description
[edited by: andyy at 10:07 PM (GMT 0) on 6 Dec 2018]
  • I have made a bit of progress, but still having issues making it work correctly. ()

    Since the example code for the AD5940/ADICUP3029 combo does not use an adi_pinmux.c file, and for some reason instead sets up the peripherals (UART/SPI/GPIO) by setting individual bits in relevant registers explicitly in AD5940_MCUResourceInit(), and UrtCfg(), I only just realized that the same thing has to be done to enable I2C on the I2C pins. Setting this up in a pinmux file, does enable the I2C which is now active!

    #include <ADuCM3029.h>
    #define I2C0_SCL0_PORTP0_MUX  ((uint16_t) ((uint16_t) 1<<8))
    #define I2C0_SDA0_PORTP0_MUX  ((uint16_t) ((uint16_t) 1<<10))
    int32_t adi_initpinmux(void);
    int32_t adi_initpinmux(void) {
        /* Port Control MUX registers */
        return 0;

    However, this breaks the SPI and UART communication, and halts the code again! I suspect since the config data (pADI_GPIO0) for these are overwritten when I define I2C in the pinmux file. Is there an easier way to make I2C behave without writing abstract init code as that which initializes SPI/UART (in AD5940_MCUResourceInit() in ADICUP3029Port.c and UrtCfg() in main.c)?



  • 0
    •  Analog Employees 
    on Dec 12, 2018 7:58 AM over 1 year ago in reply to andyy


    Could you try:


    This should set the mux for the I2C pins without affecting the other pins.

    Also, what versions of DFP and BSP are you using? I will have a look at the problem with the semaphore too.



  • Hi Andrei,

    I'm using v0.1.6 of the Evaluation Software for the AD5940 eval kit

    As mentioned adding the pinmux.c file configuring I2C with the line you've pasted above (but without the "|=") fixes the I2C communication for a single cycle, after which the code gets stuck in ADICUP3029Port.c:

    uint32_t AD5940_GetMCUIntFlag(void)
       return ucInterrupted;

    I assume, due to the interrupt service routine, also in ADICUP3029Port.c, never being called, and therefore never setting ucInterrupted to 1:

    /* MCU related external line interrupt service routine */
    void Ext_Int0_Handler()
       ucInterrupted = 1;
      /* This example just set the flag and deal with interrupt in AD5940Main function. It's your choice to choose how to process interrupt. */

    So it seems like adding:



    Activates I2C but breaks the external line interrupt which ADICUP3029 uses for SPI communication with the AD5940. All I need is to be able to run the "AD5940_BIOZ-2Wire" example from the Evaluation Software above with I2C communication to a different peripheral simultaneously.

    If I write the line as you propose, adding the "or" (|=):



    The code breaks in startup.c, on: 

    WEAK_FUNCTION( HardFault_Handler        )

    Giving me the following fault in the "Fault exception viewer":

    HardFault exception.

    The processor has escalated a configurable-priority exception to HardFault.

       An imprecise data access error has occurred.

    Exception occured at: 0x66b2

    See the call stack for more information.



  • 0
    •  Analog Employees 
    on Dec 13, 2018 8:33 AM over 1 year ago in reply to andyy

    Hello Andreas,

    If you do not "or" the I2C bits in the pin mux you are basically resetting the other pin muxes on port 0 (like the SPI ones) back to 0 (most likely the GPIO setting) and that is why the SPI and UART stop working. By adding the "or" you only set the muxes for the I2C ones leaving the rest untouched.

    Commenting out the semaphore function should not be necessary. I believe that is for a resource manager running in the background and could be the cause of the hard-fault when two devices are trying to access the same memory resource at the same time (like I2C and SPI).

    These problems can be caused by not having enough memory for the I2C driver. What is "devMem" in the code? It should be a memory array the size of ADI_I2V_MEMORY_SIZE like so:

    /* Device memory required for operate Master I2C device */
    uint8_t devMem[ADI_I2C_MEMORY_SIZE];

    Most drivers use these kinds of memory arrays and some of them must be 32 bit aligned. The I2C and SPI don't have to be, but the UART one does have to be 32 bit aligned.