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.

BQ40Z50-R3-DEVICE-FW: Read block command from SMBus library does not work as described in technical reference

Part Number: BQ40Z50-R3-DEVICE-FW

Using the BQ40z50-R3 and controlling it via a msp430 through SMBus, developers are told to use block read/block write commands for manufacturer access. I am using a MSP430FR5949 as single master with broadcasts from the bq40z50-R2 slave (running R3 firmware) turned off.

Without modifying smbus_nwk.c this is not possible for quite a few of the commands. smbus_nwk.c/SMBus_NWK_masterProcessRx(SMBus *smbus,uint8_t data) does a check on the first byte returned, which in the BQ40z50-R3 is the byte count.

Currently there is a limit of 32 bytes as per SMBus standard, however, with ManufacturerBlockAccess 0x44 0x0071 (DAStatus_1) the byte count will always be 34 or higher with PEC, making the check fail and returning an error.

There is no documentation of this anywhere (at least that I could locate). This discrepancy should at least addressed in the bq40z50-R3 technical manual as it would lead you to believe the proper method of reading from Man.BlockAccess is to perform this process to read DAStatus1 0x0071 (as example)

1.block write 0x44 (0x71, 0x00)

2. block read 0x44.

However, in practice despite the fact that the register itself only contains 32 bytes of data the first byte returns 34 which includes the data and the 2 byte address.

  • Hi, John

        The gauge can return more than 32 bytes for block reading.

        For the read block operation to MAC 0x0071, the I2C transaction sequence is like below:

        Host send: 0x44(For MAC write) 0x02(Number of Following Bytes) 0x71, 0x00(2 bytes MAC command)

        Host Send: 0x44(For MAC read)

        Gauge Return: 0x22(Num of Bytes return including 0x71, 0x00), 0x71, 0x00(MAC Command), ……(32 bytes data returned as MAC Block data), PEC(optional)

        You can use I2C protocol commands to perform above command sequence.

        For example, to read the data sent back by the gauge.

       you can firstly initiate a block reading with expected data length of 1, then you will be able to get the first byte, i.e., the data length 0x22, then without send the MAC write command, you can do the block reading again with the expected read back data length of 0x22 + 2, to include the first data length byte and the last PEC byte, which is optional.

       I tried this method with Aardvark I2C host adaptor on PC, it works. I think it should also work on MCU, as I2C engine is typical supported by most MCUs

     

  • I understand what you're saying, but this is a problem I spent hours trying to solve and eventually did. This is the general call (as I mentioned using the TI supplied SMBus library) 

    smbus.SMBus_masterReadBlock() --> smbus_nwk.SMBus_NWK_startTxTransfer() -->  smbus_phy.SMBus_PHY_masterStartTx() --> smbus_phy.SMBus_PHY_masterProcessInt() (UCTXIFG0 is set for sending 0x44 ManufacturerAccessBlock cmd to slave) --> smbus_phy.SMBus_NWK_masterProcessTx() 

    slave receives command and the first byte of data is returned to master (UCRXIFG0 is now set) --> smbus_phy.SMBus_PHY_masterProcessInt() --->

    smbus_nwk.SMBus_NWK_masterProcessRx(SMBus *smbus,uint8_t data) (this is where the error is generated)

    at this point nwk.rxIndex = 0 , nwk.rxLen = 3 (this is set to 3 by default in smbus.SMBus_masterReadBlock() ) and the first byte (0x20) = data

    from smbus_nwk.SMBus_NWK_masterProcessRx(SMBus *smbus,uint8_t data)

    {

        if((smbus->nwk.rxIndex == 0) &&
           (smbus->nwk.eState == SMBus_NwkState_RX_Block))
        {
            // Update the length based on received Byte count
            if((data == 0) || (data > 32))
    { SMBus_PHY_masterSendStop(smbus); smbus->status.bits.packErr = 1; smbus->nwk.eState = SMBus_NwkState_Error; smbus->state = SMBus_State_DataSizeError; return(smbus->state); } else { smbus->nwk.rxLen = data + 1; // One extra byte due to Byte count #ifdef SMB_PEC_SUPPORTED if(smbus->ctrl.bits.pecEn == 1) { smbus->nwk.rxLen++; } #endif }

    }

    as you can see since the first byte of data returned is 0x20 = 34 this check will always throw an error unless the byte count data received is subtracted by 2 to equal 32 or the if((data == 0) || (data > 32)) is modified to 

    if((data == 0) || (data > 34))  or a more universal check against the actual byte_count of block received

    I'm sure someone more versed in working with SMBus would have known something like this or the libraries aren't meant to be used except as a reference only, either way from simply reading the technical reference and its' description of the process someone like me who is not an expert in the process is left with the impression that simply using the supplied libraries and the masterWriteBlock/ masterReadBlock functions will give you the expected results. Which, at least in my case it did not.

  • Hi, John

        My understanding is that you have already fixed this issue by modifying the code in the TI supplied Library.

        I think this library may not designed for communicating with TI gas gauge, as present TI gauge can give response to block read with the returned block length longer than 32.

        But I agree a description on the command and data format for BLOCK reading could be helpful for the user to develop the code for SMBUS operation.