This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G3507: SMBus Target Doesn't Respond to Controller Read Requests

Part Number: MSPM0G3507
Other Parts Discussed in Thread: SYSCONFIG

I have a single MSPM0G3507 evaluation board with two configured I2C modules as SMBus modules, one acts as a controller and the other acts a target, I connected both of the SDA and SCL lines with external pull up resistors. I'm also using the SMBus library provided with the MSPM0 SDK.

I have tried sending write commands from the controller to the target using the SMBus_controllerSendByte() and it works with no issues, whoever when attempting a read request, such as SMBus_controllerReadBlock(), the target doesn't receive any interrupts. My code is based on the SMBus controller and target examples provided by the SDK.

#include <stdint.h>
#include "ti_msp_dl_config.h"
#include <ti/smbus/smbus.h>
#include <string.h>

static SMBus SMBControllerInst;
static SMBus SMBTargetInst;
static SMBus_State currentBusState;
static uint8_t targetRxBuff[SMB_MAX_PACKET_SIZE];
static uint8_t targetTxBuff[SMB_MAX_PACKET_SIZE];
static uint8_t controllerRxBuff[SMB_MAX_PACKET_SIZE + 4];


int main(void)
{
    bool RXExpected;
    int8_t ret;

    SYSCFG_DL_init();

    NVIC_ClearPendingIRQ(SMB_I2C_CONTROLLER_INST_INT_IRQN);
    NVIC_EnableIRQ(SMB_I2C_CONTROLLER_INST_INT_IRQN);

    NVIC_ClearPendingIRQ(SMB_I2C_TARGET_INST_INT_IRQN);
    NVIC_EnableIRQ(SMB_I2C_TARGET_INST_INT_IRQN);

    SMBus_controllerInit(&SMBControllerInst, SMB_I2C_CONTROLLER_INST, 32000000);

    SMBus_targetInit(&SMBTargetInst, SMB_I2C_TARGET_INST);
    SMBus_targetSetAddress(&SMBTargetInst, SMB_I2C_TARGET_TARGET_OWN_ADDR);
    SMBus_targetSetRxBuffer(&SMBTargetInst, targetRxBuff, sizeof(targetRxBuff));
    SMBus_targetSetTxBuffer(&SMBTargetInst, targetTxBuff, sizeof(targetTxBuff));
    SMBus_targetEnableInt(&SMBTargetInst);

    while(1)
    {
        ret = SMBus_controllerReadBlock(&SMBControllerInst, SMB_I2C_TARGET_TARGET_OWN_ADDR, 0x3, controllerRxBuff);

        if(ret == SMBUS_RET_OK)
        {

            if(SMBus_controllerWaitUntilDone(&SMBControllerInst, 100000) != SMBUS_RET_OK)
            {
                ret = SMBus_State_TimeOutError;
                SMBus_controllerReset(&SMBControllerInst);
            }
            else
            {
                ret = currentBusState;
            }

            if(ret == SMBus_State_OK)
            {
                int controllerRxLen = SMBus_getRxPayloadAvailable(&SMBControllerInst);

                if(controllerRxLen >= 1)
                {
                    if(controllerRxBuff[1] == 'b') {
                        DL_GPIO_togglePins(LED_GROUP_PORT, LED_GROUP_LED_0_PIN);
                    }
                    else {
                        DL_GPIO_togglePins(LED_GROUP_PORT, LED_GROUP_LED_1_PIN);
                    }
                }
                else
                {
                    ret = SMBus_State_Target_Error;
                }
            }
        }

        SMBControllerInst.status.u8byte = 0x00;
        delay_cycles(20000000);
    }
}

void SMB_I2C_CONTROLLER_INST_IRQHandler(void) {
    currentBusState = SMBus_controllerProcessInt(&SMBControllerInst);
}

static uint8_t rxCmd = 1;

void SMB_I2C_TARGET_INST_IRQHandler(void) {
    const SMBus_State currentState = SMBus_targetProcessInt(&SMBTargetInst);
    switch(currentState)
        {
        case SMBus_State_Target_FirstByte:
            rxCmd = SMBus_targetGetCommand(&SMBTargetInst);
            break;
        case SMBus_State_Target_CmdComplete:
        {
            char dataToSend[5];
            uint32_t len = 0;

            if(rxCmd == 0x3)
            {
                strcpy(dataToSend, "bbbb");
                len = 4;
            }
            else
            {
                strcpy(dataToSend, "rrr");
                len = 3;
            }
            SMBTargetInst.nwk.txBuffPtr[0] = len;
            uint32_t i = 0;
            for(i = 0 ; i < len ; i++) {
                SMBTargetInst.nwk.txBuffPtr[i+1] = dataToSend[i];
            }
            SMBTargetInst.nwk.txLen = len + 1;
            break;
        }
        default:
            break;
        }

    SMBus_processDone(&SMBTargetInst);
}


The code is supposed to read a block of data from the target every 20M cycles, I'm always sending a command code 0x3 which commands the target to send a block of data of 4 bytes "bbbb", once the controller receives the block of data, it will check if the 1st byte of the RX buffer is 'b' then toggles the blue LED, however nothing happens, and it never reaches a breakpoint assigned to the top of target interrupt handler. I don't know what could be wrong here, I'm attaching the sample project file in case it is needed.

All help is appreciated. Thanks.

SMBus Test.zip

  • Hi Mohammad,

    Apologies for the delay on an answer here. Your code is actually running well with no modifications on my end. 

    I think there must be a difference in our setups. What is your CCS version, your MSPM0 SDK Version, and your SysConfig version? 

    Also, are you using a Production launchpad or an early sample launchpad? Production launchpads will be marked "Rev A", early sample launchpads will be marked "Rev 1.0".

    Can you tell me how you are connecting the target to the controller? There is a spot for pullups on PB2 and PB3 (R59 and R60), but they are not populated by default, can you verify the presence and value of pullups on your SMBUS lines? 

    Best Regards,
    Brandon Fisher

  • Thanks for the reply,

    Here's the equipment I work with:
    - CCS version 12.3.0.00005
    - MSPM0 SDK version 1.10.0.05
    - SysConfig version: 1.17.0
    - MSPM0G3507 Rev 1.0

    I'm connecting the target and the controller with external 4.7k resistors on a breadboard, I have tested write commands on the same setup, which means that it is probably not the cause of the issue.

    On a side note it would be great to teach us how we can use R59 and R60 as pull-ups, because we can't figure it out from reading the EVM guide.

    Thanks for the help.

  • Hi Mohammad,

    That launchpad is an early sample launchpad, so it needs to be used with Early sample revisions of the SDK (any version less than 1.x) CCS (12.1 or 12.0) , and Sysconfig (1.15.2826). You would also need to manually install the support package for MSPM0.

    Those early sample versions of Sysconfig, the SDK, and the support package, are available only from the MySecureSoftware folder. I'd recommend we upgrade you to a Rev A launchpad since they are available now. That way you can just use the most recent, publicly available tools and production silicon.

    For the Rev A launchpad you will want to upgrade to CCS 12.4 as well. After that your setup will match what I'm testing with and you should see correct function.

    Best Regards,

    Brandon Fisher

  • Hi Bradon,

    I tried to downgrade to the versions suggested above, however I had no luck in getting the workspace working without errors, so I had to wait for my Rev A board to arrive and everything is working perfectly fine now.

    However, one thing I noticed is that the first byte of the communication is always 0, which triggers the red LED to toggle (This is not intended), then the blue LED will start flashing as intended. Do you know what could be the issue here?

    Thanks.

  • Hi Mohammad,

    I'm happy its mostly working now.

    I can actually see this on my end too. I'm currenlty looking into it. At the moment it looks like the Controller IRQ handler is firing during our read block function (not unexpected), but is erroneously loading the buffer with 0x00 on the first transmit.

    Best Regards,
    Brandon Fisher