Richard-Gemmell / teensy4_i2c

An I2C library for the Teensy 4. Provides slave and master mode.
MIT License
94 stars 21 forks source link

improved reliability by using glitch filters #19

Closed hbitter closed 1 year ago

hbitter commented 3 years ago

Hi Richard, I'm using your Lib now for quite a while in the DNMS project (you can search GitHub for getting some more info about DNMS). Teensy4 is used as a slave giving noise measurements to a connected communication processor (NodeMCU or Pi Zero W) acting as the master. At the beginning there were some problems but this could be solved by setting the IOMUXC_PAD_HYS bit.

In one configuration there was still a problem all the time: Teensy4.0 slave was not running in parallel to an other I²C slave (SPS30 PM sensor from Sensirion), only one or the other was running on the I²C bus. The strange thing was, I had some early Teensy4.0 boards where everything was ok, so it took some time that people informed me about the problem. With newer Teens4.0 boards I had that problem as well. Teensy4.0 didn' t recognized the slave address, no reaction at all.

My findings are: the problems seems to be a "glitch" problem. I can eleminate the strange behavior by setting the glitch filter in Teensy4.0 I²C slave section. Perhaps it will make the I²C communication more reliable and maybe it's worth to make it configurable in the lib. Only few lines in imx_rt1060_i2c_driver.cpp are necessary:

void IMX_RT1060_I2CSlave::listen(uint32_t samr, uint32_t address_config) {
    // Make sure slave mode is disabled before configuring it.
    stop_listening();

    // Halt and reset Slave Mode if it's running
    port->SCR = (LPI2C_SCR_RST | LPI2C_SCR_RRF | LPI2C_SCR_RTF);
    port->SCR = 0;

    initialise_common(config, pad_control_config);

    // Set the Slave Address
    port->SAMR = samr;

    // Enable clock stretching
    port->SCFGR1 = (address_config | LPI2C_SCFGR1_TXDSTALL | LPI2C_SCFGR1_RXSTALL);
    port->SCFGR2 = (LPI2C_SCFGR2_FILTSDA(15) | LPI2C_SCFGR2_FILTSCL(15));

    // Set up interrupts
    attachInterruptVector(config.irq, isr);
    port->SIER = (LPI2C_SIER_RSIE | LPI2C_SIER_SDIE | LPI2C_SIER_TDIE | LPI2C_SIER_RDIE);
    NVIC_ENABLE_IRQ(config.irq);

    // Enable Slave Mode
    port->SCR = LPI2C_SCR_SEN | LPI2C_SCR_FILTEN;
}

Don' t know if the value 15 I used for the glitch filters is really the best value but it worked for me.

Best Regards, Helmut

Richard-Gemmell commented 3 years ago

Hi Helmut,

Your project looks cool!

Thanks very much for this suggestion. I'm planning to do some more work on the driver later this year and I'll include an option to enable the glitch filter.

cheers, Richard

Richard-Gemmell commented 1 year ago

Glitch filters are enabled by default in slave mode in the v2 driver. I've confirmed that the timings work at all bus speeds.