Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: I2C works on Teensy 4.0, but not on same chip's EVB. SCL differs.

  1. #1

    I2C works on Teensy 4.0, but not on same chip's EVB. SCL differs.

    Let me know if I should be on NXP's forum rather than Teensy's...

    I can use the Teensy 4.0 to talk with my Si514 and it'll acknowledge (ACK) back. Furthermore, I can control it perfectly. However, the evaluation board (EVB) for the same chip does not result in ACK when using the EVB's I2C drivers.

    Successful ACK from the Si514 being driven by the Teensy 4.0. Slave address 0x55.
    Click image for larger version. 

Name:	Teensy successful ACK PNG.png 
Views:	4 
Size:	23.4 KB 
ID:	18050

    No ACK from the Si514 being driven by the EVB's included drivers. It looks identical except for no ACK and the SCL line is not high as long. In other words, the SCL's duty cycle is shorter. It's about 37%. It seems to *start later*, not end earlier. I assume we want 50% duty cycle like in the teensy 4.0. This may be the problem? If it is I have no idea how to change/fix it. Does anyone?
    Click image for larger version. 

Name:	RT1020EVB NACK PNG.png 
Views:	5 
Size:	23.3 KB 
ID:	18051

    If you overlay the two pictures, it's obvious that the only difference is the SCL clock width while high (duty cycle), and of course the ACK bit difference on the end. Could the SCL duty cycle cause this problem? Does anyone know how to change this in the included EVB driver? I've been through a lot of settings in it but can't seem to find a way to modify the clock itself.

    Why would NXP's driver put out an asymmetrical SCL???? That seems so strange!

    There is this struct in the EVB driver, but none seem to affect SCL's duty cycle. I've played with various values of many of these to no avail.

    typedef struct _lpi2c_master_config
    {
    bool enableMaster; /*!< Whether to enable master mode. */
    bool enableDoze; /*!< Whether master is enabled in doze mode. */
    bool debugEnable; /*!< Enable transfers to continue when halted in debug mode. */
    bool ignoreAck; /*!< Whether to ignore ACK/NACK. */
    lpi2c_master_pin_config_t pinConfig; /*!< The pin configuration option. */
    uint32_t baudRate_Hz; /*!< Desired baud rate in Hertz. */
    uint32_t busIdleTimeout_ns; /*!< Bus idle timeout in nanoseconds. Set to 0 to disable. */
    uint32_t pinLowTimeout_ns; /*!< Pin low timeout in nanoseconds. Set to 0 to disable. */
    uint8_t sdaGlitchFilterWidth_ns; /*!< Width in nanoseconds of glitch filter on SDA pin. Set to 0 to disable. */
    uint8_t sclGlitchFilterWidth_ns; /*!< Width in nanoseconds of glitch filter on SCL pin. Set to 0 to disable. */
    struct
    {
    bool enable; /*!< Enable host request. */
    lpi2c_host_request_source_t source; /*!< Host request source. */
    lpi2c_host_request_polarity_t polarity; /*!< Host request pin polarity. */
    } hostRequest; /*!< Host request options. */
    } lpi2c_master_config_t;

    This struct and two other parameters are passed to a function to start the transfer by sending out the address (0x55 in this case).

    My eyes were also drawn to these two functions that set up clocks, but I can't find any way to modify SCL's duty cycle inside them.

    /*Clock setting for LPI2C*/
    CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT);
    CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER);
    Last edited by kingforger; 10-29-2019 at 08:07 PM.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    Quote Originally Posted by kingforger View Post
    .... I have no idea how to change/fix it. Does anyone?
    The info you seek is in section 46.4.1.13 of the reference manual (Rev 1, 12/2018) starting on page 2902.


    Why would NXP's driver put out an asymmetrical SCL????
    Whoever wrote their driver probably didn't put much effort into the timing details, as I did for many hours of trial & error with my oscilloscope when I wrote Teensy 4.0's Wire lib.

  3. #3
    Thank you so much!! I found the reference manual on your website.

  4. #4
    If anyone's wondering how to change SCL duty cycle in the EVB drivers, I've got a way thanks to Paul's clue. In fsl_lpi2c.c:

    Change
    value |= LPI2C_MCCR0_CLKLO(2 * bestClkHi) | LPI2C_MCCR0_SETHOLD(bestClkHi) | LPI2C_MCCR0_DATAVD(bestClkHi / 2);
    to
    value |= LPI2C_MCCR0_CLKLO(1 * bestClkHi) | LPI2C_MCCR0_SETHOLD(bestClkHi) | LPI2C_MCCR0_DATAVD(bestClkHi / 2);

    Add
    bestClkHi = bestClkHi * 3 / 2;
    just above the line
    value = LPI2C_MCCR0_CLKHI(bestClkHi);

    They purposefully set the low period to be twice the length of the high period! Their comment was "Assume CLKLO = 2*CLKHI". I'm still not sure why they do that, but they did it on purpose. Perhaps it's to allow more time slack for certain slaves to respond? I'm not sure.

    The second thing I did isn't strictly good code, ideally I'd change the function that sets bestClkHi. I also don't know if this works for anything but standard 100kHz speed or not, though I think it will. But I get about 50.5% duty cycle now! You can see in the picture below.

    Click image for larger version. 

Name:	RT1020EVB duty cycle fix.png 
Views:	1 
Size:	23.8 KB 
ID:	18055

    I'm still not getting a ACK at the end from my slave device despite the fact that my pulse train looks practically identical now... I'll have to continue thinking. I have pull-up resistors on both. I cut the SCL/SDA traces to the other I2C device that shares the lines on the EVB... I might have to investigate SETHOLD or DATAVD.
    Last edited by kingforger; 10-30-2019 at 05:26 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •