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.

MSP430FR2433: Possible DriverLib bug in I2C set data rate

Part Number: MSP430FR2433


In DriverLib eusci_b_i2c.c in function EUSCI_B_I2C_initMaster() this code seems in error and doesn't seem to match the comment.

/*
* Compute the clock divider that achieves the fastest speed less than or
* equal to the desired speed. The numerator is biased to favor a larger
* clock divider so that the resulting clock is always less than or equal
* to the desired clock, never greater.
*/
preScalarValue = (uint16_t)(param->i2cClk / param->dataRate);
HWREG16(baseAddress + OFS_UCBxBRW) = preScalarValue;

The division is unsigned and fraction is truncated. Thus the preScalarValue (the clock divider) is smaller and the actual data rate (frequency) greater than desired.

For example for param->i2cClk of 1M and param->dataRate of 400k (the max I2C data rate), preScalarValue is 2 (2.5 with fraction truncated).
Thus the actual data rate will be 500kbps, which is FASTER than desired.

I don't see any code that "biased" the numerator.

CCS 8.02 and a fairly recent version of MSPWare DriverLib

  • Hi lloyd,

    The comments just reminds us what needs care during the clock configuration, although there is only one register for the frequency division setting besides the source selection, just as the UG description,

    back to the real case of I2C, you can balance the clock source frequency setting(.i.e, flexible frequency setting of SMCLK) and prescaler setting so as to get the targeted frequency, hope this is helpful to you.

  • No, I am still confused.

    My code initializes param->i2cClk= 1000000 and param->dataRate=EUSCI_B_I2C_SET_DATA_RATE_400KBPS. My intent is that the I2C bus data rate be 400kHz or less, which is the maximum supported by the two chips (the MSP430 and the slave) and my intent is that the clock source for the bitrate generator is SMCLK which is 1Mhz.  EUSCI_B_I2C_SET_DATA_RATE_400KBPS is defined in the .h as 400000.

    The code in EUSCI_B_I2C_initMaster() seems to set UCBxBRW to 2 (integer division of 1,000,000/400,000 yields 2 since the fraction is truncated according to the C language.)

    You cite that “The BITCLK frequency is given by: fBRCLK/UCBRx.” In my case, fBRCLK is 1Mhz and UCBRx is 2 (another name for the 16-bits of register UCBxBRW). That yields a BITCLK frequency of 500kHz, which is not my intent.

    The cited text “The minimum high and low periods of the generated SCL are: tLOW,MIN = tHIGH,MIN = (UCBRx/2)/fBRCLK when UCBRx is even” applies since UCBRx IS even. It also yields tLOW,MIN and tHIGH,MIN both equal to 1/1,000,000. But that also means that the frequency (the number of high pulses per second) is 500kHz. (You can specify the frequency of a square wave in two ways, either as high pulses per second, or duration in seconds of each pulse. The cited text seems to redundantly specify the data rate both ways.)

    I thought that the DriverLib implementation is hiding or abstracting some of the complexity of setting the data rate. I thought that choosing EUSCI_B_I2C_SET_DATA_RATE_400KBPS would yield 400kbps, but according to what you cited, it yields 500kbps.

    Also, you cite “The maximum bit clock that can be used in single master mode is fBRCLK/4.” That seems to say that my intent is not supported, that if one chooses the SMCLK at 1Mhz, the eUSCI_B will only work at 250khz. It seems to imply that one can set UCBxBRW to a value such that the eUSCI_B won’t work. And that the DriverLib code does not protect you from doing that. It is strange, because my code seems to work (at 500kbps?) but I could just be lucky? I don’t really know the measured I2C SCL frequency since I don’t have a scope.

    Since I don’t trust the DriverLib code, a workaround is to just set UCBxBRW myself. To value 4 which should yield a data rate of 250kbps.

  • Hi lloyd,

    Those description about maximum and minimum bit clock pulse is for the reference of scenario when the synchronization between masters and slavers happens. For the frequency setting, we just need to use formula of fBRCLK/UCBRx. You can easily find the driverlib follows this way,

    the variable param is to check current SMCLK frequency and get targeted frequency from macro EUSCI_B_I2C_SET_DATA_RATE_400KBPS, and function EUSCI_B_I2C_initMaster is to finish the configuration, during which the prescaler value is calculated from SMCLK and the targeted data rate.

    So for your case of 400bps, you can set combination of SMCLK&UCBRx to be 2000000&5 or 4000000&10.

  • Yes, if I don’t use the DriverLib function but write to the eUSCI_B registers directly, I can set the data rate properly.

    Or, if I read the implementation of the DriverLib function, I will know to pass it “fudged” parameters, as you say: 2,000,000 and 5, and then it will set the data rate properly.

    But my point is that if one just reads the API documentation of the DriverLib function, one might be misled.

    In the code which you show above, (if SMCLK is 1Mhz) the data rate will be 500kbps (according to my math, don’t you agree?)

    Which contradicts that you passed the value EUSCI_B_I2C_SET_DATA_RATE_400KBPS. The programmer thinks they are choosing 400kbps, but they get 500kbps.
  • Hi lloyd,

    Get your point, I will suggest the driverlib owner to add necessary information into the comments. This should tell the source clock frequency setting during I2C bit clock configuration. Thanks a lot!

**Attention** This is a public forum