Description
Basic Infos
- This issue complies with the issue POLICY doc.
- I have read the documentation at readthedocs and the issue is not addressed there.
- I have tested that the issue is present in current master branch (aka latest git).
- I have searched the issue tracker for a similar issue.
- If there is a stack dump, I have decoded it.
- I have filled out all fields below.
Platform
- Hardware: [ESP-12]
- Core Version: [2.6.0 - 2.6.2]
- Development Env: [Arduino IDE]
- Operating System: [MacOS]
Settings in IDE
- Module: [Lolin (Wemos) D1 mini & r2]
- Flash Mode: []
- Flash Size: [4MB:FS 1 Mb OTA]
- lwip Variant: [v2 Lower Memory]
- Reset Method: [nodemcu]
- Flash Frequency: [40Mhz]
- CPU Frequency: [80Mhz|160MHz]
- Upload Using: [OTA]
- Upload Speed: []
Problem Description
I am interfacing a ESP8266 as a slave trough I2C with a old legacy system as master in order to read parameters from the system. It is a slow I2C communication, 10 KHz and I have been running with the ESP8266 for about one year with core versions starting from 2.5.0 an up.
It has been working resonable good, with some glitches in the communication where it was hanging once in a while. I solved that hanging by simply reboot.
After 2.6.0 the communication seems to be more stable but there is a new issue. When I start to do a OTA update the ESP chrashes as soon there is some data on the SDA line.
In order to do debugging I set up two wemos D1 mini's. They were connected to each other like this:
GPIO 4 (pin D2) <----> GPIO 4 (pin D2)
GPIO 5 (pin D1) <----> GPIO 5 (pin D1)
Ground <----> Ground
I tried to use the ESP826 Wire examples: master_writer and slave_receiver combined with BasicOTA but couldn't get them running properly. However, If I used 160MHz clock it worked.
I then did a change in core_esp8266_si2c.cpp to the Twi::setClock function adding some longer delays and thereby managed to get the slowest clockspeed down to about 12KHz in order to mimic the behaviour of the legacy system.
After that I also could run the sketches on 80MHz.
The line 108 in core_esp8266_si2c.cpp that is causing Exception 0: Illegal instruction says:
return (GPI & (1 << twi_sda)) != 0;
I hope I supplied all relevant inf and that it wasn't to long-winded.
MCVE Sketch
master_writer.ino :
#include <Wire.h>
#include <PolledTimeout.h>
#define SDA_PIN 4
#define SCL_PIN 5
const int16_t I2C_MASTER = 0x42;
const int16_t I2C_SLAVE = 0x08;
void setup() {
Serial.begin(74880); // start serial for output
Serial.println();
Serial.println("Starting...");
Wire.begin(SDA_PIN, SCL_PIN, I2C_MASTER); // join i2c bus (address optional for master)
Wire.setClock(10000);
}
byte x = 0;
void loop() {
using periodic = esp8266::polledTimeout::periodicMs;
static periodic nextPing(1000);
if (nextPing) {
Wire.beginTransmission(I2C_SLAVE); // transmit to device #8
Wire.write("x is "); // sends five bytes
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting
Serial.println (x);
x++;
}
}
slave_receiver.ino
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
#include <Wire.h>
#define SDA_PIN 4
#define SCL_PIN 5
const int16_t I2C_MASTER = 0x42;
const int16_t I2C_SLAVE = 0x08;
void setup() {
Serial.begin(9600); // start serial for output
Serial.println();
Serial.println("Booting and connecting to WiFi");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
// ================ i2c =====================
Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave)
Wire.onReceive(receiveEvent); // register event
// =============== OTA =====================
ArduinoOTA.setHostname("i2cproblemdemo");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
ArduinoOTA.handle();
}
void receiveEvent(size_t howMany) {
(void) howMany;
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
core_esp8266_si2c.cpp
void Twi::setClock(unsigned int freq)
{
preferred_si2c_clock = freq;
#if F_CPU == FCPU80
if (freq <= 10000)
{
twi_dcount = 200; //about 12KHz
}
else if (freq <= 50000)
{
twi_dcount = 38; //about 50KHz
}
else if (freq <= 100000)
{
twi_dcount = 19; //about 100KHz
}
else if (freq <= 200000)
{
twi_dcount = 8; //about 200KHz
}
else if (freq <= 300000)
{
twi_dcount = 3; //about 300KHz
}
else if (freq <= 400000)
{
twi_dcount = 1; //about 400KHz
}
else
{
twi_dcount = 1; //about 400KHz
}
#else
if (freq <= 10000)
{
twi_dcount = 254; //about 12KHz
}
else if (freq <= 50000)
{
twi_dcount = 64; //about 50KHz
}
else if (freq <= 100000)
{
twi_dcount = 32; //about 100KHz
}
else if (freq <= 200000)
{
twi_dcount = 14; //about 200KHz
}
else if (freq <= 300000)
{
twi_dcount = 8; //about 300KHz
}
else if (freq <= 400000)
{
twi_dcount = 5; //about 400KHz
}
else if (freq <= 500000)
{
twi_dcount = 3; //about 500KHz
}
else if (freq <= 600000)
{
twi_dcount = 2; //about 600KHz
}
else
{
twi_dcount = 1; //about 700KHz
}
#endif
}
Debug Messages
Decoded stack trace:
Exception 0: Illegal instruction
PC: 0x40206134: Twi::SDA_READ() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_si2c.cpp line 108
EXCVADDR: 0x00000000
Decoding stack results
0x40100b74: interrupt_handler(void*) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/interrupts.h line 29
0x4010022c: ets_post(uint8, ETSSignal, ETSParam) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_main.cpp line 160
0x40100ab0: interrupt_handler(void*) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_wiring_digital.cpp line 135
0x40100ff4: umm_free_core(void*) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/umm_malloc/umm_malloc.cpp line 316
0x4021e12a: ip4_output_if at core/ipv4/ip4.c line 1550
0x4021ecc3: ip_chksum_pseudo at core/inet_chksum.c line 395
0x40219673: tcp_output_control_segment at core/tcp_out.c line 1956
0x40219569: tcp_output_alloc_header at core/tcp_out.c line 1863
0x40219ebc: tcp_send_empty_ack at core/tcp_out.c line 2057
0x40219faa: tcp_output at core/tcp_out.c line 1319
0x4020462d: Print::write(char const*) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/Print.h line 60
0x4020411e: EspClass::flashEraseSector(unsigned int) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/Esp.cpp line 585
0x40205ba6: __yield() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_main.cpp line 100
0x40204e37: UpdaterClass::_writeBuffer() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/Updater.cpp line 323
0x40205b77: __esp_yield() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_main.cpp line 107
0x402064c1: __delay(unsigned long) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_wiring.cpp line 57
0x40203b52: ArduinoOTAClass::_runUpdate() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/Updater.h line 154
0x402089e8: esp8266::MDNSImplementation::MDNSResponder::_updateProbeStatus() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp line 1321
0x402094f9: esp8266::MDNSImplementation::MDNSResponder::_process(bool) at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp line 90
0x40203cb0: ArduinoOTAClass::handle() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/libraries/ArduinoOTA/ArduinoOTA.cpp line 365
0x402013e0: loop() at /Volumes/home/Data/Verksamheter/Elektronik/Arduino/Demo i2c ota error/slave_receiver/slave_receiver/slave_receiver.ino line 118
0x40205c8c: loop_wrapper() at /Users/christer/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.2/cores/esp8266/core_esp8266_main.cpp line 180