The i2c peripheral will hang if a READ request is issued with a zero data length. The peripheral
drops into a continuous timeout interrupt response. The STOP command can not be set out to the I2C
bus. The SLAVE device correctly ACK'd the address byte, with READ bit set, it has control of the SDA
pin. The ESP32 send out the next SCL HIGH pulse but, since the SLAVE is in READ Mode, and the First
bit it is sending happened to be a ZERO, the ESP32 cannot send the STOP. When it releases SDA during
the SCL HIGH, the pin does not change state. The pin stays low because the SLAVE is outputing a LOW!
The ESP32 drops into a perminent WAIT state waiting for SDA to go HIGH (the STOP).
**esp32-hal-i2c.c**
* add databuff length checks to `i2cRead()` and `i2cWrite()`
* Add APB change callbacks and move cpu code to own file
* Properly set esp_timer and FreeRTOS tick dividers
* Improve updated devisors
* No need to update REF_TICK yet
* Add initial handling for UART baud change
* fix uartWriteBuf and uartDetectBaudrate
* trigger callbacks even when APB did not change
* toggle UART ISR on CPU change
* add XTAL freq getter and add cpu freq validation
* Support CPU frequency changes in I2C (#2287)
**esp32-hal-i2c.c**
* add callback for cpu frequency changes
* adjust fifo thresholds based on cpu frequency and i2c bus frequency
* reduce i2c bus frequency if differential is too small
**Wire.h**
* version to 1.1.0
* Implement clock change for the other peripherals
* remove bad CPU clock values from the menu
* Add note to CPU freqs that support WiFi and BT
The I2C hardware has limitations on min and max bus frequency directly related to CPU frequency, bus speed cannot be greater than 1/100 CPU clock, nor less than CPU clock / 8192.
* Add support to HAL for APB frequencies different than 80MHz
* Add support for CPU frequencies in the IDE board menu
* Switch to fast set_config
* Add method to uart so debug can be reassigned after apb frequency switch
* Return real APB frequency
* Fix error in PR #2048: if ::available() is called before ::connect() _rxBuffer is not initialised
* Fixed flash size check and added SPIFFS size check
* Rewriting ESP.getFreeSketchSpace(), moving code from HTTPUpdate.cpp
* Clean warnings when all warning enabled
Not used variables / functions due to debug log
Dual define with different values :
cores\esp32/binary.h
#define B110 6
#define B1000000 64
tools/sdk/include/newlib/sys/termios.h
#define B110 3
#define B1000000 23
Local variable returned in WiFiclient Secure
* change due to deprecated function
* Update with proper variable and label
* Update esp32-hal-i2c.c
* Apply changes requested
* Fix warnings due to #define conflict thanks @atanisoft
* Added baudrate detection to esp32-hal-uart and HardwareSerial
* Solved compiler warning for uartResizeRxBuffer()
* Add unit to header variable name (timeout_ms)
* Reverting accidentally changed files to master
* Add small delay after baudrate detection
#1869 exposed a resource exhaustion issue. The current HAL layer for I2C support is designed to use a shared interrupt, But, during debugging to solve the interrupt overloading condition identified in #1588, and the generation of pr #1717, the interrupt allocation parameters were changed. This change was unnecessary, the code will work successfully with shared interrupts. So, there is no need to assign a private interrupt for each I2C peripheral.
* TX Flow Control and Code cleanup
* Use semaphore instead of delay
TX functionality is done.
* Use single buffer and empty queue on exit
* Fix compile issues because of LwIP code relocation
* Add temporary header to fix Azure not compiling
* Fix AsyncUDP early init
* AsyncUDP Multicast fixes
* Add source mac address and rework multicast
* Allow redefinition of default pins for Serials 1 and 2
* Update IDF to 3276a13
* Update esptool.py to 2.5.0
* Fix sketches
* Fix log level in BluetoothSetial
* rmt driver initial version
* supporting conti mode plus interrupts
* using conitnous mode for sending more data
* working continous mode
* rmt driver cleanup after conti mode
* initial version of rmt driver
* adding a simple example
* adding channel and block locks
* modified of rmt interface for simpler/easier usage
* adding header sentinels, split interface to common and additional settings
* Fixes per code review + support for rx callback mode
* renamed internal structures and enums, fixed formatting
* cmake support for rmt
* refactored tx-conti interrupts to function to make it more readable
* added Tx and Rx examples
* added license headers
* minor updates per review
* used struct access, renamed defines, corrected diagram
If the esp32 is reset during a i2c read cycle the slave device may be in control of the SDA line.
If the SDA line is held low, the esp32 cannot issue a START or STOP to recover the bus.
The previous code did not correctly configure the SCL output pin, and it cycled SCL 9 times with SDA Low. Since the slave device was in a READ cycle, it just continued outputting the bits of the current byte. When the ACK/NAK bit space occurred, The low output value of SDA was interpreted as ACK so the slave device continued with the next byte. It never terminated the READ cycle.
This new code will correctly recover from an interrupted READ
* ReSTART fix, Sequencing fix
pr #1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill. during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence. The problem manifested as an ACK error.
In addition to this required bug fix I propose:
* `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported. Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure.
* `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus. With the functional change to `Wire.begin()` this allows app level recover of a hung bus.
* `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()` had no room to record the directed address bytes. It generated just a NAK check without setting the EEPROMs internal register address. The succeeding ReSTART read succeeded at incorrect address.
* Changes to the HAL layer:
** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently
** added `i2cDebug()` programmatic control of debug buffer output
** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers.
** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points
*
* Update esp32-hal-i2c.c
* Update Wire.cpp
* ReSTART, Sequencing
pr #1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill. during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence. The problem manifested as an ACK error.
In addition to this required bug fix I propose:
* `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported. Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure.
* `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus. With the functional change to `Wire.begin()` this allows app level recover of a hung bus.
* `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()` had no room to record the directed address bytes. It generated just a NAK check without setting the EEPROMs internal register address. The succeeding ReSTART read succeeded at incorrect address.
* Changes to the HAL layer:
** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently
** added `i2cDebug()` programmatic control of debug buffer output
** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers.
** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points
*
* Forgot DebugFlags Return
@andriyadi found this, total brain fade on my part.
This version no longer needs an interrupt for each byte transferred. It only needs interrupts for START, STOP, FIFO empty/Full or error conditions. This dramatically reduces the interrupt overhead. I think the prior version was causing an interrupt overload condition where the ISR was not able to process every interrupt as they happened.
the 'eject' ERROR is and indication of an interrupt triggering without an source. I am working to eliminate these serviceable interrupt. This update increase stability on a HelTek Wifi Lora 32 board. with a SSD1306 OLED. This update fixes a glaring error in the interrupt allocation code, the Interrupt mask was wrong. I also dynamically adjust the FiFo thresholds based on Bus clockrate. The change to FiFo thresholds has reduced the number for 'eject' events. I also change 'eject' from and ERROR to DEBUG. An 'eject' event does not compromise i2c transmissions. It happens after a transaction has completed.
Chuck.