I2C Busy State

Hello,

currently I’ve the next Problem with My I2C
In general i only want to control a MAX30100 Oxygen Sensor … anyway It Won’t work …
I always Get a busy State of my I2C …

hardware_init:

void hardware_init(void)
{
    /* Board specific RDC settings */
    BOARD_RdcInit();

    /* Board specific clock settings */
    BOARD_ClockInit();

    /* initialize debug uart */
    dbg_uart_init();


    /* Configure GPIOS */
     //configure_platform_gpio();



     /* In this example, we need to grasp board I2C exclusively */
     RDC_SetPdapAccess(RDC, BOARD_I2C_RDC_PDAP, 3 << (BOARD_DOMAIN_ID * 2), false, false);

     /* Select I2C clock derived from OSC clock(24M) */
     CCM_UpdateRoot(CCM, BOARD_I2C_CCM_ROOT, ccmRootmuxI2cOsc24m, 0, 0);
     /* Enable I2C clock */
     CCM_EnableRoot(CCM, BOARD_I2C_CCM_ROOT);
     CCM_ControlGate(CCM, BOARD_I2C_CCM_CCGR, ccmClockNeededRunWait);

     /* I2C Pin setting */
     configure_i2c_pins(BOARD_I2C_BASEADDR);
     /* RDC MU*/
     RDC_SetPdapAccess(RDC, BOARD_MU_RDC_PDAP, 3 << (BOARD_DOMAIN_ID * 2), false, false);

     /* Enable clock gate for MU*/
     CCM_ControlGate(CCM, BOARD_MU_CCM_CCGR, ccmClockNeededRun);


}

main function:

int main(void)
{


#ifdef SPI_MAX30100
    /* Setup I2C init structure. */
    i2c_init_config_t i2cInitConfig = {
        .baudRate     = 400000u,
        .slaveAddress = 0x00
    };
#endif

    //uint8_t i;
    hardware_init();

#ifdef SPI_MAX30100
    /* Get current module clock frequency. */
    i2cInitConfig.clockRate = get_i2c_clock_freq(BOARD_I2C_BASEADDR);
#endif




    PRINTF("Init GPIO Pins\r\n");
    /* GPIO module initialize, configure "LED" as output and button as interrupt mode. */
    GPIO_Ctrl_Init();


#ifdef SPI_MAX30100
    PRINTF("[1].Initialize the I2C module with initialize structure. \n\r");
    I2C_Init(BOARD_I2C_BASEADDR, &i2cInitConfig);
    /* Finally, enable the I2C module */
    PRINTF("[2].Enable the I2C module at BOARD_I2C_BASEADDR. \n\r");
    I2C_Enable(BOARD_I2C_BASEADDR);
    //BOARD_I2C_MAX30100_ADDR
    PRINTF("[3].Default Initalization of MAX30100. \n\r");
    defaultInit(&max30100_1);
    PRINTF("[4].Sucessfully initalized I2C module. \n\r");

    PRINTF("[5.2].Initialize Heart Rate Task. \n\r");
    /* Create a demo task. */
    xTaskCreate(MAX30100_Task, "Heart Rate Task", APP_TASK_STACK_SIZE,
                NULL, tskIDLE_PRIORITY+1, NULL);
#endif

    /* Start FreeRTOS scheduler. */
    vTaskStartScheduler();
    PRINTF("[ERR] Schedule Broke!. \n\r");
    /* Should never reach this point. */
    while (true);
}

Checking State before doing Anything:

    if (I2C_GetStatusFlag(device->base, i2cStatusBusBusy)){
         retval = false;
          PRINTF("I2C Received Busy Flag! \r\n");
    }

The status flag always returns TRUE so It won’t get Further …

I’ve also tried the I2C Example enclosed in your FreeRTOS Examples (inside git)

Kind regards
Patrick

Dear @PatrickNies

Did you measure the signals on your i2c bus?
Bus-busy usually indicates that the SDA signal (or the SCL) is constantly low. This can be caused by:

  • A short circuit to GND
  • Another i2c device driving the signal low (this can also rarely happen if the system was reset in the middle of a communication, and the i2c slave device is not connected to a hardware-reset)
  • SDA pin not being configured to the i2c alternate function
  • I2c controller configured to use a different pin than expected (and this other pin is low)
  • Missing or too high impedance pull-up resistor

Can you first try to access the M41T0 RTC on the Evalboard - Do a simple read/write to (7-bit slave address 0x68)? So I would have the same hardware available to reproduce the problem.

Regards Andy

Hi Andy,
unfortunately I still get a busy flag …

I’ve unplugged everything from my Evaluation Board (except USB, Serial).
I’ve used standard Toradex Linux as base

When Starting the module I stop the Auto Boot and entering following Commands:

fatload mmc 0:1 ${loadaddr} SPI.elf
bootaux ${loadaddr}

Here is my code:

////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
#define APP_TASK_STACK_SIZE 256

static uint8_t txBuffer[5];
static uint8_t rxBuffer[7];
static uint8_t cmdBuffer[5];

/* I2C information for this board */
#define BOARD_I2C_RDC_PDAP                    rdcPdapI2c4
#define BOARD_I2C_CCM_ROOT                    ccmRootI2c4
#define BOARD_I2C_CCM_CCGR                    ccmCcgrGateI2c4
#define BOARD_I2C_BASEADDR                    I2C4
#define BOARD_I2C_IRQ_NUM                     I2C4_IRQn
#define BOARD_I2C_HANDLER                     I2C4_Handler
#define BOARD_I2C_FXAS21002_ADDR              (0x20)
#define BOARD_I2C_FXOS8700_ADDR               (0x1E)
#define BOARD_I2C_MAX30100_ADDR               (0XAE)
#define BOARD_I2C_M41T0_ADDR                  (0x68)


bool I2C_MasterSendDataPolling(I2C_Type *base,
                                      const uint8_t *cmdBuff,
                                      uint32_t cmdSize,
                                      const uint8_t *txBuff,
                                      uint32_t txSize)
{
    if (I2C_GetStatusFlag(base, i2cStatusBusBusy)){
         PRINTF("I2C::SEND Received Busy Flag! \r\n");
         return false;
    }


    /* Set I2C work under Tx mode */
    I2C_SetDirMode(base, i2cDirectionTransmit);

    /* Switch to Master Mode and Send Start Signal. */
    I2C_SetWorkMode(base, i2cModeMaster);

    /* Send first byte */
    if (0 != cmdSize)
    {
        I2C_WriteByte(base, *cmdBuff++);
        cmdSize--;
    }
    else
    {
        I2C_WriteByte(base, *txBuff++);
        txSize--;
    }

    while (1)
    {
        /* Wait I2C transmission status flag assert.  */
        while (!I2C_GetStatusFlag(base, i2cStatusInterrupt));

        /* Clear I2C transmission status flag. */
        I2C_ClearStatusFlag(base, i2cStatusInterrupt);

        /* Transmit complete. */
        if ((I2C_GetStatusFlag(base, i2cStatusReceivedAck)) ||
            ((0 == txSize) && (0 == cmdSize)))
        {
            /* Switch to Slave mode and Generate a Stop Signal. */
            I2C_SetWorkMode(base, i2cModeSlave);

            /* Switch back to Rx direction. */
            I2C_SetDirMode(base, i2cDirectionReceive);
            return true;
        }
        else
        {
            if (0 != cmdSize)
            {
                I2C_WriteByte(base, *cmdBuff++);
                cmdSize--;
            }
            else
            {
                I2C_WriteByte(base, *txBuff++);
                txSize--;
            }
        }
    }
}

 bool I2C_MasterReceiveDataPolling(I2C_Type *base,
                                         const uint8_t *cmdBuff,
                                         uint32_t cmdSize,
                                         uint8_t *rxBuff,
                                         uint32_t rxSize)
{
    uint32_t currentDir = i2cDirectionReceive;

    /* Clear I2C interrupt flag to avoid spurious interrupt */
    I2C_ClearStatusFlag(base, i2cStatusInterrupt);

    if (I2C_GetStatusFlag(base, i2cStatusBusBusy))
    {
        PRINTF("I2C::RECEIVE Received Busy Flag! \r\n");
        return false;
    }

    /* Set I2C work under Tx mode */
    I2C_SetDirMode(base, i2cDirectionTransmit);

    /* Switch to Master Mode and Send Start Signal. */
    I2C_SetWorkMode(base, i2cModeMaster);

    if (0 != cmdSize)
    {
        currentDir = i2cDirectionTransmit;
        if (1 == cmdSize)
            I2C_SendRepeatStart(base);
        I2C_WriteByte(base, *cmdBuff++);
        cmdSize--;
    }
    else
    {
        /* Change to receive state. */
        I2C_SetDirMode(base, i2cDirectionReceive);

        if (1 == rxSize)
            /* Send Nack */
            I2C_SetAckBit(base, false);
        else
            /* Send Ack */
            I2C_SetAckBit(base, true);
        /* dummy read to clock in 1st byte */
        *rxBuff = I2C_ReadByte(base);
    }

    while (1)
    {
        /* Wait I2C transmission status flag assert.  */
        while (!I2C_GetStatusFlag(base, i2cStatusInterrupt));

        /* Clear I2C transmission status flag. */
        I2C_ClearStatusFlag(base, i2cStatusInterrupt);

        if (i2cDirectionTransmit == currentDir)
        {
            if (0 < cmdSize)
            {
                if (I2C_GetStatusFlag(base, i2cStatusReceivedAck))
                {
                    /* Switch to Slave mode and Generate a Stop Signal. */
                    I2C_SetWorkMode(base, i2cModeSlave);

                    /* Switch back to Rx direction. */
                    I2C_SetDirMode(base, i2cDirectionReceive);
                    return false;
                }
                else
                {
                    if (1 == cmdSize)
                        I2C_SendRepeatStart(base);
                    I2C_WriteByte(base, *cmdBuff++);
                    cmdSize--;
                }
            }
            else
            {
                /* Change to receive state. */
                I2C_SetDirMode(base, i2cDirectionReceive);
                currentDir = i2cDirectionReceive;

                if (1 == rxSize)
                    /* Send Nack */
                    I2C_SetAckBit(base, false);
                else
                    /* Send Ack */
                    I2C_SetAckBit(base, true);
                /* dummy read to clock in 1st byte */
                *rxBuff = I2C_ReadByte(base);
            }
        }
        else
        {
            /* Normal read operation. */
            if (2 == rxSize)
                /* Send Nack */
                I2C_SetAckBit(base, false);
            else
                /* Send Nack */
                I2C_SetAckBit(base, true);

            if (1 == rxSize)
                /* Switch back to Tx direction to avoid additional I2C bus read. */
                I2C_SetDirMode(base, i2cDirectionTransmit);
            *rxBuff = I2C_ReadByte(base);
            rxBuff++;
            rxSize--;

            /* receive finished. */
            if (0 == rxSize)
            {
                /* Switch to Slave mode and Generate a Stop Signal. */
                I2C_SetWorkMode(base, i2cModeSlave);

                /* Switch back to Rx direction. */
                I2C_SetDirMode(base, i2cDirectionReceive);

                return true;
            }
        }
    }
}

void hardware_init(void)
{
    /* Board specific RDC settings */
    BOARD_RdcInit();

    /* Board specific clock settings */
    BOARD_ClockInit();

    /* initialize debug uart */
    dbg_uart_init();


    /* Configure GPIOS */

     /* In this example, we need to grasp board I2C exclusively */
     RDC_SetPdapAccess(RDC, BOARD_I2C_RDC_PDAP, 3 << (BOARD_DOMAIN_ID * 2), false, false);

     /* Select I2C clock derived from OSC clock(24M) */
     CCM_UpdateRoot(CCM, BOARD_I2C_CCM_ROOT, ccmRootmuxI2cOsc24m, 0, 0);
     /* Enable I2C clock */
     CCM_EnableRoot(CCM, BOARD_I2C_CCM_ROOT);
     CCM_ControlGate(CCM, BOARD_I2C_CCM_CCGR, ccmClockNeededRunWait);

     /* I2C Pin setting */
     configure_i2c_pins(BOARD_I2C_BASEADDR);
  


}


int main(void)
{

    /* Setup I2C init structure. */
    i2c_init_config_t i2cInitConfig = {
        .baudRate     = 400000u,
        .slaveAddress = 0x00
    };

    //uint8_t i;
    hardware_init();

    PRINTF("[1].Initialize the I2C module with initialize structure. \n\r");
    I2C_Init(BOARD_I2C_BASEADDR, &i2cInitConfig);

    PRINTF("[2].Enable the I2C module at BOARD_I2C_BASEADDR. \n\r");
    I2C_Enable(BOARD_I2C_BASEADDR);

    cmdBuffer[0] = BOARD_I2C_M41T0_ADDR << 1;
    cmdBuffer[1] = 0x00;
    txBuffer[0]  = 0x01;
    I2C_MasterSendDataPolling(BOARD_I2C_BASEADDR, cmdBuffer, 2, txBuffer, 1);

    cmdBuffer[0] = BOARD_I2C_M41T0_ADDR << 1;
    cmdBuffer[1] = 0x01;
    txBuffer[0]  = 0x80;
    I2C_MasterSendDataPolling(BOARD_I2C_BASEADDR, cmdBuffer, 2, txBuffer, 1);

    PRINTF("[ERR] Schedule Broke!. \n\r");

}

Kind regards
Patrick

Dear @PatrickNies

I successfully tested accessing the RTC on the Evalboard. I attached the full source files I used, along with the resulting binary:

If this doesn’t work for you, please send me the complete source, so I can debug your code 1:1.

Regards, Andy