Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAX32655 - I2C driver hangs forever #1289

Open
lsampaio-adi opened this issue Dec 9, 2024 · 2 comments
Open

MAX32655 - I2C driver hangs forever #1289

lsampaio-adi opened this issue Dec 9, 2024 · 2 comments

Comments

@lsampaio-adi
Copy link

Hi,
I am working with a MAX32655 custom board with 2 I2C devices on the same bus (I2C1). The devices are ADXL343 and MAX31328. After experimenting with the I2C example, I noticed that sometimes the driver would just hang after running for a while.

When trying using the sync function MXC_I2C_MasterTransaction, it would not return. When trying to use the async function MXC_I2C_MasterTransactionAsync or MXC_I2C_MasterTransactionDMA, the interrupt would never come.

Using a logic analyzer, it seems to be a state machine issue with the I2C driver, as sometimes the STOP condition would never happen or the MAX32655 would not send an ACK.

As my board is based on the MAX32655FTHR, I tried to reproduce the issue with the 2 I2C components on the board (the Audio Codec and the PMIC). The main code below, when compiled for the Feather board, hangs. However, if you uncomment lines 124 and 149 (thus printing to the console), then it works.

I could not find a similar issue here with the I2C driver. Have you seen this problem before?

Thank you!

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mxc_device.h"
#include "mxc_delay.h"
#include "nvic_table.h"
#include "i2c.h"
#include "dma.h"
#include "rtc.h"
#include "wut.h"

#define I2C_FREQ 400000
#define I2C_TCXO_ADDR 0x68
#define I2C_ACCEL_ADDR 0x53
#define I2C_BYTES 8

#define I2C_PMIC_ADDR 0b0101000
#define I2C_CODEC_ADDR 0b0011000

static uint8_t txdata[I2C_BYTES];
static uint8_t rxdata[I2C_BYTES];
volatile int I2C_FLAG;

void I2C_Callback(mxc_i2c_req_t *req, int error)
{
    I2C_FLAG = error;
    if (error) {
        printf("Callback: Error code: %d\n", error);
        while(1);
    }
}

void I2C1_IRQHandler(void)
{
    MXC_I2C_AsyncHandler(MXC_I2C1);
}

int main(void)
{
    mxc_i2c_req_t reqMaster;
    printf("\n******** I2C MAX31328 Test ********\n");

    MXC_Delay(MXC_DELAY_SEC(1));

    NVIC_EnableIRQ(I2C1_IRQn);

    int error = 0;

    if (MXC_I2C_Init(MXC_I2C1, 1, 0) != E_NO_ERROR) {
        printf("[ERROR] Could not configure I2C master\n");
        return 1;
    }
    MXC_I2C_SetFrequency(MXC_I2C1, I2C_FREQ);

    for (int i = 0; i < 100; i++) {
        memset(txdata, 0, I2C_BYTES);
        memset(rxdata, 0, I2C_BYTES);
        txdata[0] = 0x00;

        reqMaster.i2c = MXC_I2C1;
        reqMaster.addr = I2C_PMIC_ADDR;
        reqMaster.tx_buf = txdata;
        reqMaster.tx_len = 1;
        reqMaster.rx_buf = rxdata;
        reqMaster.rx_len = 1;
        reqMaster.restart = 0;
        reqMaster.callback = I2C_Callback;
        I2C_FLAG = 1;

        if ((error = MXC_I2C_MasterTransactionAsync(&reqMaster)) != 0) {
            printf("Error writing: %d\n", error);
            return error;
        }
        while(I2C_FLAG);

        printf("[%02i] HardwareID: %02x\n", i, rxdata[0]);

        // ================================================================ //

        memset(txdata, 0, I2C_BYTES);
        memset(rxdata, 0, I2C_BYTES);
        txdata[0] = 0x01;

        reqMaster.i2c = MXC_I2C1;
        reqMaster.addr = I2C_PMIC_ADDR;
        reqMaster.tx_buf = txdata;
        reqMaster.tx_len = 1;
        reqMaster.rx_buf = rxdata;
        reqMaster.rx_len = 1;
        reqMaster.restart = 0;
        reqMaster.callback = I2C_Callback;
        I2C_FLAG = 1;

        if ((error = MXC_I2C_MasterTransactionAsync(&reqMaster)) != 0) {
            printf("Error writing: %d\n", error);
            return error;
        }
        while(I2C_FLAG);

        printf("[%02i] FirmwareID: %02x\n", i, rxdata[0]);

        // ================================================================ //

        memset(txdata, 0, I2C_BYTES);
        memset(rxdata, 0, I2C_BYTES);
        txdata[0] = 0x0F;

        reqMaster.i2c = MXC_I2C1;
        reqMaster.addr = I2C_PMIC_ADDR;
        reqMaster.tx_buf = txdata;
        reqMaster.tx_len = 1;
        reqMaster.rx_buf = rxdata;
        reqMaster.rx_len = 4;
        reqMaster.restart = 0;
        reqMaster.callback = I2C_Callback;
        I2C_FLAG = 1;

        if ((error = MXC_I2C_MasterTransactionAsync(&reqMaster)) != 0) {
            printf("Error writing: %d\n", error);
            return error;
        }
        while(I2C_FLAG);

        // printf("[%02i]\n", i); // UNCOMMENT THIS LINE

        // ================================================================ //

        memset(txdata, 0, I2C_BYTES);
        memset(rxdata, 0, I2C_BYTES);
        txdata[0] = 0x17;
        txdata[1] = 0x80;

        reqMaster.i2c = MXC_I2C1;
        reqMaster.addr = I2C_CODEC_ADDR;
        reqMaster.tx_buf = txdata;
        reqMaster.tx_len = 2;
        reqMaster.rx_buf = rxdata;
        reqMaster.rx_len = 0;
        reqMaster.restart = 0;
        reqMaster.callback = I2C_Callback;
        I2C_FLAG = 1;

        if ((error = MXC_I2C_MasterTransactionAsync(&reqMaster)) != 0) {
            printf("Error writing: %d\n", error);
            return error;
        }
        while(I2C_FLAG);

        // printf("[%02i]\n", i); // UNCOMMENT THIS LINE

        // ================================================================ //

        memset(txdata, 0, I2C_BYTES);
        memset(rxdata, 0, I2C_BYTES);
        txdata[0] = 0x00;

        reqMaster.i2c = MXC_I2C1;
        reqMaster.addr = I2C_CODEC_ADDR;
        reqMaster.tx_buf = txdata;
        reqMaster.tx_len = 1;
        reqMaster.rx_buf = rxdata;
        reqMaster.rx_len = 1;
        reqMaster.restart = 0;
        reqMaster.callback = I2C_Callback;
        I2C_FLAG = 1;

        if ((error = MXC_I2C_MasterTransactionAsync(&reqMaster)) != 0) {
            printf("Error writing: %d\n", error);
            return error;
        }
        while(I2C_FLAG);

        printf("[%02i] Status: %02x\n", i, rxdata[0]);
    }

    MXC_I2C_Shutdown(MXC_I2C1);

    return E_NO_ERROR;
}
@JordanAceto
Copy link

This sounds similar to the recently closed #1261

I am not sure that the fix merged in pull request #1263 fixed the issue. I have been meaning to reopen the issue, but I haven't had time to set up a reproducible test case.

I am still/also seeing infinite loops when calling MXC_I2C_RevA_MasterTransaction(), but it moved to a different while loop.

Before the fix in pull request #1263 I saw it hang here:

while (!(i2c->mstctrl & MXC_F_I2C_REVA_MSTCTRL_STOP)) {}

After 1263 I now see it hang here:

while (!(i2c->intfl0 & MXC_F_I2C_REVA_INTFL0_DONE)) {}

The temporary hack my team has been doing is to replace line 997 in i2c_reva.c with this line:

while (!(i2c->intfl0 & MXC_F_I2C_REVA_INTFL0_STOP)) {}

This brings the behavior back to pre-commit 79c0d9a.

I am not sure if we're doing the perfect thing, but I just thought I'd mention that there is a closed issue describing the same thing, and I don't think the fix committed actually fixed it.

@lsampaio-adi
Copy link
Author

Thank you for the detailed response.

Yes, I saw the issue and the pull request, I thought this was going to solve it, but as you said, this moved to a different loop, so I don't think it solved the problem.

I will try the temporary hack on my side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants