MCF8316A: I2C Address is NACKed

Part Number: MCF8316A
Other Parts Discussed in Thread: DRV10983, , , TM4C123GH6PM, MSP-EXP430FR2355, MSP430FR2355

Hello,

we designed a new PCB with the MCF8316A and a microcontroller. We successfully used nearly the same PCB with the DRV10983 for years and only adapted it for the MCF8316A.

The problem is, that there is no I2C communication possible. After the first byte with the 0x01 address and the write bit, the MCF8316A does not send an ACK:

AVDD, DVDD and buck regulator voltages are as expected, so it seems to be soldered correctly.

  • Hi Thomas, 

    Our team will look into this request and aim to provide a response tomorrow.

    In the meantime, may want to refer to the device datasheets/user-guides and see if there's any requirements regarding I2C in this device

    • (e.g. pull-up resistance needed, protocol frame size and structure, communication speed and voltage) 

    Best Regards, 
    Andrew 

  •  Could it be a problem that I connected the speed pin to AVDD? We had problems with a sleep version of the DRV10983 so I did this to make sure, that it can not go to sleep. Maybe this is not ideal but I would expect the I2C communication to work nervertheless.

    I also did not connect the NC pins to GND since it was not mentioned in the data sheet.

  • Hi Thomas,

    Thanks for the additional info - we will investigate further and aim to provide a response next week

    Best Regards, 
    Andrew 

  • Hi Thomas,

    Firstly, there is a specific I2C communication requirement on this device where a 100-µs delay should be inserted in between every byte sent from the host.

    However, this is probably not the issue, since the MCF8316A appears to NACK after the host sends the address + W byte.

    I would recommend to try pulling the SPEED pin to low on power-up. By default, DEV_MODE is set to 0b, which means the device will simply enter standby mode if SPEED pin is 0V. Having 3.3V on SPEED pin means the MCF8316A will immediately attempt and probably fail to spin-up the device (it'll try to run MPET, since no motor parameters were programmed into the EEPROM and fail since MAX_SPEED is also not configured by default).

    Not connecting NC to GND shouldn't be an issue. The only possible downside, if any, is you're potentially losing a very small amount of thermal dissipation via the device package -> copper GND pour surrounding the device.

    Additionally, could you please also help me clarify the following:

    1. What host microcontroller are you using to send I2C commands?
    2. Is the microcontroller implementing I2C using hardware peripheral or software bit-banging?

    Lastly, do you have an MCF8316AEVM? If so, you could try jumper wiring the I2C + GND pins from the MSP430 bridge interface of the EVM to your PCB and use the EVM's GUI to verify whether the I2C issue is with the MCF8316A or the host MCU.

    Regards,
    Eric C.

  • Hi Eric,

    thanks for your response. I also don't think that the 100-us delay is the problem, since the first byte is NACKed. Sadly, we don't have an MCF8316AEVM since it seems to be sold out everywhere. To pull the SPEED pin low, I will have to order new prototypes of our PCB.

    1. We are using a TM4C123GH6PM.

    2. We are using the driverlib/i2c.h library from TI with commands like I2CMasterSlaveAddrSet etc. It worked perfectly with various devices including the DRV10983.

    Regards,

    Thomas

  • Hi Thomas,

    A few more questions:

    1. I'd like to confirm whether you're using an RTM or APL (pre-release) version of the device. Could you please check the device marking on the MCF8316A's package?
      1. RTM devices should say MCF8316A...
      2. APL devices should say PMCF8316A...
    2. Could you please help measure and verify the following voltage regulator outputs:
      1. Buck regulator (5V by default)
      2. AVDD (3.3V)
      3. DVDD (1.5V)
    3. What I2C pull-up resistor value are you using on the SDA and SCL lines?

    Thanks,
    Eric C.

  • Hi Eric,

    1. It seems to be the RTM version.

    2. As written above, the three voltages are correct.

    3. We were using 4,7k pull-up resistors. I also changed them to 2k for testing but it did not help.

    Regards

    Thomas

  • Hi Thomas, 

    Thanks for the additional info - will review further and follow up soon

    Best Regards, 
    Andrew 

  • Hi Thomas,

    Would it be possible for you to provide the TM4C123GH6PM project with the I2C read/write code for me to review?

    Alternatively, you could also order a MSP-EXP430FR2355 LaunchPad and use the attached example I2C read/write project for the MSP430FR2355 here:

    HardwareI2C_MSP430FR2355_MCF8316AEVM.zip 

    Regards,
    Eric C.

  • Hi Eric,

    these are the helper functions I use for communication.

    3666.i2c_helpers.c
    #include "i2c_helpers.h"
    #include "helpers.h"
    
    #include "inc/hw_memmap.h"
    
    #include <stdbool.h> // required by driverlib
    #include <stdint.h>
    #include "driverlib/i2c.h"
    #include "driverlib/sysctl.h"
    
    
    void i2c_init(uint32_t i2cBase)
    {
        uint32_t sysctlPeriph;
        switch (i2cBase)
        {
            case I2C0_BASE:
                sysctlPeriph = SYSCTL_PERIPH_I2C0;
                break;
    
            case I2C1_BASE:
                sysctlPeriph = SYSCTL_PERIPH_I2C1;
                break;
    
            case I2C2_BASE:
                sysctlPeriph = SYSCTL_PERIPH_I2C2;
                break;
    
            case I2C3_BASE:
                sysctlPeriph = SYSCTL_PERIPH_I2C3;
                break;
    
            default:
                return;
        }
        // enable I2C module 0
        SysCtlPeripheralEnable(sysctlPeriph);
        while (!SysCtlPeripheralReady(sysctlPeriph))
            ;
    
        // reset module
        SysCtlPeripheralReset(sysctlPeriph);
    
        // 400KHZ is not supported by Nanomotion and does not work, so set it to
        // false for all by now.
        I2CMasterInitExpClk(i2cBase, SysCtlClockGet(), false);
    }
    
    I2C_retVal i2c_write(uint32_t i2cBase, uint8_t address, char* buf, uint8_t len)
    {
        if (len == 0)
        {
            return I2C_ERROR_OTHER;
        }
    
        I2C_retVal ret = I2C_ERROR_NONE;
        uint32_t start = g_millis;
        I2CMasterSlaveAddrSet(i2cBase, address, false);
    
        if (len == 1)
        {
            I2CMasterDataPut(i2cBase, buf[0]);
            I2CMasterControl(i2cBase, I2C_MASTER_CMD_SINGLE_SEND);
            ret = i2c_waitForTransmission(i2cBase, start);
        }
        else
        {
            I2CMasterDataPut(i2cBase, buf[0]);
            I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_SEND_START);
            ret = i2c_waitForTransmission(i2cBase, start);
    
            if (ret == I2C_ERROR_NONE)
            {
                // put all except last data byte into I2C buffer
                for (uint8_t i = 1; i < len - 1; ++i)
                {
                    I2CMasterDataPut(i2cBase, buf[i]);
                    I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_SEND_CONT);
                    ret = i2c_waitForTransmission(i2cBase, start);
                    if (ret != I2C_ERROR_NONE)
                    {
                        break;
                    }
                }
            }
    
            // put last data byte into I2C buffer
            I2CMasterDataPut(i2cBase, buf[len - 1]);
            I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_SEND_FINISH);
            if (ret == I2C_ERROR_NONE)
            {
                ret = i2c_waitForTransmission(i2cBase, start);
            }
            else
            {
                while (I2CMasterBusy(i2cBase) && (g_millis - start < I2C_TIMEOUT_MS))
                ;
            }
        }
    
        return ret;
    }
    
    I2C_retVal i2c_read(uint32_t i2cBase, uint8_t address, char* buf, uint8_t len)
    {
        if (len == 0)
        {
            return I2C_ERROR_OTHER;
        }
    
        I2C_retVal ret = I2C_ERROR_NONE;
        uint32_t start = g_millis;
        I2CMasterSlaveAddrSet(i2cBase, address, true);
    
        if (len == 1)
        {
            I2CMasterControl(i2cBase, I2C_MASTER_CMD_SINGLE_RECEIVE);
            ret = i2c_waitForTransmission(i2cBase, start);
            if (ret == I2C_ERROR_NONE)
            {
                buf[0] = I2CMasterDataGet(i2cBase);
            }
        }
        else
        {
            I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_START);
            ret = i2c_waitForTransmission(i2cBase, start);
            if (ret == I2C_ERROR_NONE)
            {
                buf[0] = I2CMasterDataGet(i2cBase);
    
                // receive all except last byte
                for (uint8_t i = 1; i < len - 1; ++i)
                {
                    I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
                    ret = i2c_waitForTransmission(i2cBase, start);
                    if (ret != I2C_ERROR_NONE)
                    {
                        break;
                    }
                    buf[i] = I2CMasterDataGet(i2cBase);
                }
            }
    
            // receive last byte
            I2CMasterControl(i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
            if (ret == I2C_ERROR_NONE)
            {
                ret = i2c_waitForTransmission(i2cBase, start);
            }
            else
            {
                while (I2CMasterBusy(i2cBase) && (g_millis - start < I2C_TIMEOUT_MS))
                ;
            }
            if (ret == I2C_ERROR_NONE)
            {
                buf[len - 1] = I2CMasterDataGet(i2cBase);
            }
        }
    
        return ret;
    }
    
    I2C_retVal i2c_waitForTransmission(uint32_t i2cBase, uint32_t startTime)
    {
        while (I2CMasterBusy(i2cBase) && (g_millis - startTime <= I2C_TIMEOUT_MS))
            ;
        if (g_millis - startTime > I2C_TIMEOUT_MS)
        {
            return I2C_ERROR_TIMEOUT;
        }
        uint32_t err = I2CMasterErr(i2cBase);
        if (!err)
        {
            return I2C_ERROR_NONE;
        }
        if (err & I2C_MASTER_ERR_ADDR_ACK)
        {
            return I2C_ERROR_ADDR_ACK;
        }
        if (err & I2C_MASTER_ERR_DATA_ACK)
        {
            return I2C_ERROR_DATA_ACK;
        }
        return I2C_ERROR_OTHER;
    }
    

    When I use it the first time like this:

    i2c_write(MCF8316A_I2C_ADDRESS, buf, 7);

    With address = 0x01 and control word and data in buf I get a NACK after the address.

    Regards

    Thomas

  • Hi Thomas,

    Thanks for providing the code, please give me some time to review your code.

    Thanks,
    Eric C.

  • Hi Thomas,

    Apologies for the delayed response, but we recently found that, even when un-used, the FG pin (open drain) needs to be pulled up in order for the I2C communication to function correctly. Could you please put a 5.1-kΩ resistor pull-up from FG to AVDD then check I2C communication again?

    Thanks,
    Eric Chen

  • Hi Eric,

    we use the internal Pull-Up of the TM4C123GH6PM for the FG pin, which worked perfectly with the DRV10983. Could it be a problem, that the Pull-Up is switched on only after the microcontroller started? So does it have to be already high when the MCF8316A starts?

    Regards

    Thomas

  • Hi Thomas, Hi Eric,

    with my application I ran into the same problem, I2C address was always NACKed.
    I can confirm, at least for me, the solution with a pull-up resistor on FG to AVDD is working.

    Note: I had the AVDD not used to supply anything, on my application the microcontroller and pull-up resistors are supplied by a seperate voltage regulator. Monitoring them with an oscilloscope I found out that the seperate regulator kicks in ~100ms after AVDD is already stable. So even though I had a pull-up resistor to 3.3V, it came into effect too late.

    Solution was for me, to move that pull-up from the seperate regulator to AVDD of the MCF8316A.

    So Thomas:
    Maybe also check, what the actual time is between AVDD being stable and your internal pull-up of the microcontroller becoming effective. I can confirm the timing is relevant.

    Eric:
    Thank you for your help!

  • @Timo,

    Thanks for confirming that pull-up on FG resolved the same problem for you.

    @Thomas,

    Please let me verify this on our board and get back to you. But yes, I believe the FG pin needs to have the pull-up during the MCF8316A powerup.

  • I was not able to measure the time from AVDD high to the TM4C123GH6PM pullup, since the MCF8316A pulled the FG line low.

    But after I added the pullup from FG to AVDD, I2C communication works.

    Thanks for your Help, Eric and Timo.

    Regards

    Thomas

  • Hi Thomas,

    Glad to hear that you were able to resolve the I2C issue.

    We will update the datasheet to indicate that a pull-up resistor on FG is required on power-up.

    Regards,
    Eric C.