-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Description
Board
ESP32-S2
Device Description
Custom ESP32-S2 based on the Lolin S2 Mini Wemos
Hardware Configuration
GPIO35 and GPIO35 are connected to SDA and SCL, respectively. My test device is a CAT24M01 EEPROM
Version
latest stable Release (if not listed below)
Type
Bug
IDE Name
VSCode with pioarduino
Operating System
Windows 11
Flash frequency
40 MHz
PSRAM enabled
yes
Upload speed
921600
Description
As previously discussed with @me-no-dev on issue #12045, I recently migrated my project to the latest Core under pioarduino using the platformio.ini lines to get the latest Core:
[env_default]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
board = lolin_s2_mini
framework = arduinoAfter managing to fix several bugs manually (since the new core broke several parts of my project after the migration), I encountered an issue that I cannot find a solution for this topic: making the I2C to operate stably above 100 kHz.
If I initialise the Wire object at 100 kHz, my sketch seems to work fine and the clock looks stable, according to my logic analyser (Kingst LA5032):
Sketch Output:
src/I2C_Fast_Test/I2C_Fast_Test.cpp<CR>
23:13:02<CR>
[S:SETUP] Starting I2C Test<CR>
[I2C] Clock set to 100000 Hz<CR>
[EEPROM] Writing 21 (0x15) to address 0<CR>
[EEPROM] Writing 22 (0x16) to address 1<CR>
[EEPROM] Writing 'A' (0x41) to address 65536 (crossing 64KB boundary)<CR>
[EEPROM] Read addr 0 = 65 (0x41)<CR>
[EEPROM] Read addr 1 = 22 (0x16)<CR>
[EEPROM] Read addr 65536 = 65 (char 'A', 0x41)<CR>
00000000 41 16 08 09 FF FF FF FF FF FF FF FF FF FF FF FF
00000010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000040 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000050 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000060 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000070 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000080 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF <CR>
TIME: 717366<CR>
[TEST] Sequential 10-byte write/read verification<CR>
[TEST] Start offset: 65530<CR>
[TEST] Page index: 255<CR>
[TEST] Page offset in page: 250<CR>
[WARN] Sequence crosses a 256-byte page boundary (multi-byte page writes would need splitting).<CR>
[TEST] Writing bytes (value = index)<CR>
[WRITE] addr=65530 value=0 (0x0)<CR>
[WRITE] addr=65531 value=1 (0x1)<CR>
[WRITE] addr=65532 value=2 (0x2)<CR>
[WRITE] addr=65533 value=3 (0x3)<CR>
[WRITE] addr=65534 value=4 (0x4)<CR>
[WRITE] addr=65535 value=5 (0x5)<CR>
[WRITE] addr=65536 value=6 (0x6)<CR>
[WRITE] addr=65537 value=7 (0x7)<CR>
[WRITE] addr=65538 value=8 (0x8)<CR>
[WRITE] addr=65539 value=9 (0x9)<CR>
[TEST] Reading back and verifying<CR>
[READ] addr=65530 got=0 (0x0) expected=0 [OK]<CR>
[READ] addr=65531 got=1 (0x1) expected=1 [OK]<CR>
[READ] addr=65532 got=2 (0x2) expected=2 [OK]<CR>
[READ] addr=65533 got=3 (0x3) expected=3 [OK]<CR>
[READ] addr=65534 got=4 (0x4) expected=4 [OK]<CR>
[READ] addr=65535 got=5 (0x5) expected=5 [OK]<CR>
[READ] addr=65536 got=6 (0x6) expected=6 [OK]<CR>
[READ] addr=65537 got=7 (0x7) expected=7 [OK]<CR>
[READ] addr=65538 got=8 (0x8) expected=8 [OK]<CR>
[READ] addr=65539 got=9 (0x9) expected=9 [OK]<CR>
[RESULT] Errors: 0<CR>
[RESULT] All 10 bytes verified successfully.<CR>
<CR>
Done...<CR>Logic analyser:
Please pay attention to the time markers A1 and A2, which show a difference of 10 us (very stable 100 kHz):
Now, if I change the frequency of the I2C Wire object to 400 kHz the communication seems to work fine, based on the analyser and serial outputs:
src/I2C_Fast_Test/I2C_Fast_Test.cpp<CR>
23:08:56<CR>
[S:SETUP] Starting I2C Test<CR>
[I2C] Clock set to 400000 Hz<CR>
[EEPROM] Writing 21 (0x15) to address 0<CR>
[EEPROM] Writing 22 (0x16) to address 1<CR>
[EEPROM] Writing 'A' (0x41) to address 65536 (crossing 64KB boundary)<CR>
[EEPROM] Read addr 0 = 65 (0x41)<CR>
[EEPROM] Read addr 1 = 22 (0x16)<CR>
[EEPROM] Read addr 65536 = 65 (char 'A', 0x41)<CR>
00000000 41 16 08 09 FF FF FF FF FF FF FF FF FF FF FF FF
00000010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000040 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000050 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000060 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000070 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000080 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00000090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
000000F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF <CR>
TIME: 624813<CR>
[TEST] Sequential 10-byte write/read verification<CR>
[TEST] Start offset: 65530<CR>
[TEST] Page index: 255<CR>
[TEST] Page offset in page: 250<CR>
[WARN] Sequence crosses a 256-byte page boundary (multi-byte page writes would need splitting).<CR>
[TEST] Writing bytes (value = index)<CR>
[WRITE] addr=65530 value=0 (0x0)<CR>
[WRITE] addr=65531 value=1 (0x1)<CR>
[WRITE] addr=65532 value=2 (0x2)<CR>
[WRITE] addr=65533 value=3 (0x3)<CR>
[WRITE] addr=65534 value=4 (0x4)<CR>
[WRITE] addr=65535 value=5 (0x5)<CR>
[WRITE] addr=65536 value=6 (0x6)<CR>
[WRITE] addr=65537 value=7 (0x7)<CR>
[WRITE] addr=65538 value=8 (0x8)<CR>
[WRITE] addr=65539 value=9 (0x9)<CR>
[TEST] Reading back and verifying<CR>
[READ] addr=65530 got=0 (0x0) expected=0 [OK]<CR>
[READ] addr=65531 got=1 (0x1) expected=1 [OK]<CR>
[READ] addr=65532 got=2 (0x2) expected=2 [OK]<CR>
[READ] addr=65533 got=3 (0x3) expected=3 [OK]<CR>
[READ] addr=65534 got=4 (0x4) expected=4 [OK]<CR>
[READ] addr=65535 got=5 (0x5) expected=5 [OK]<CR>
[READ] addr=65536 got=6 (0x6) expected=6 [OK]<CR>
[READ] addr=65537 got=7 (0x7) expected=7 [OK]<CR>
[READ] addr=65538 got=8 (0x8) expected=8 [OK]<CR>
[READ] addr=65539 got=9 (0x9) expected=9 [OK]<CR>
[RESULT] Errors: 0<CR>
[RESULT] All 10 bytes verified successfully.<CR>
<CR>
Done...<CR>HOWEVER, zooming into the SCL line shows a different story. Please look at the markers A1-A2 and B1-B2:
There seems to be some sort of clock stretching going on on my system. I am using 10 kOhms pull-ups.
Any ideas would be very much appreciated
Sketch
//* Requirements: I2C_CAT24M01 library from Rob Tillaart (https://github.com/RobTillaart/I2C_CAT24M01) and the EEPROM chip
#include <Arduino.h>
#include <HardwareSerial.h>
#include "I2C_CAT24M01.h"
constexpr int I2C_BMS_SDA = 33;
constexpr int I2C_BMS_SCL = 35;
// ---- Setting default clock speeds for the I2C Bus
static constexpr uint32_t I2C_CLOCK_STANDARD = 100000; // 100 kHz
static constexpr uint32_t I2C_CLOCK_FAST = 400000; // 400 kHz
static constexpr uint32_t I2C_CLOCK_FAST_PLUS = 800000; // 800 kHz
static constexpr uint32_t I2C_CLOCK_CRAZY = 1000000; // 1 MHz
I2C_CAT24M01 ee(0x57);
uint32_t start, stop;
HardwareSerial *dbg = &Serial0;
// I2C link bus (Wire1)
TwoWire *i2c_port = &Wire;
// Initializes the debug serial port
void dump(uint32_t from, uint32_t to);
void test(uint32_t offset);
void setup()
{
dbg->begin(115200);
delay(500);
if (dbg != nullptr)
{
dbg->println(__FILE__);
dbg->println(__TIME__);
dbg->println(F("[S:SETUP] Starting I2C Test"));
}
// I2C bus setup (same pins as showcase)
i2c_port->setPins(I2C_BMS_SDA, I2C_BMS_SCL);
i2c_port->begin();
i2c_port->setClock(I2C_CLOCK_FAST); // adjust if you use FAST/FASTPLUS per pinout.h
dbg->print(F("[I2C] Clock set to "));
dbg->print(i2c_port->getClock());
dbg->println(F(" Hz"));
if (!ee.begin())
{
dbg->println("EEPROM not found...");
while (1)
;
}
dbg->println(F("[EEPROM] Writing 21 (0x15) to address 0"));
ee.writeByte(0, 21);
dbg->println(F("[EEPROM] Writing 22 (0x16) to address 1"));
ee.writeByte(1, 22);
dbg->println(F("[EEPROM] Writing 'A' (0x41) to address 65536 (crossing 64KB boundary)"));
ee.writeByte(65536, 'A');
uint8_t v0 = ee.readByte(0);
dbg->print(F("[EEPROM] Read addr 0 = "));
dbg->print(v0);
dbg->print(F(" (0x"));
dbg->print(v0, HEX);
dbg->println(')');
uint8_t v1 = ee.readByte(1);
dbg->print(F("[EEPROM] Read addr 1 = "));
dbg->print(v1);
dbg->print(F(" (0x"));
dbg->print(v1, HEX);
dbg->println(')');
uint8_t vMid = ee.readByte(65536);
dbg->print(F("[EEPROM] Read addr 65536 = "));
dbg->print(vMid);
dbg->print(F(" (char '"));
dbg->print((char)vMid);
dbg->print(F("', 0x"));
dbg->print(vMid, HEX);
dbg->println(')');
start = micros();
dump(0x00, 0x0100);
stop = micros();
dbg->print("\nTIME: \t");
dbg->println(stop - start);
test(65530);
dbg->println("\nDone...");
}
// ------------------------ Loop ------------------------
void loop()
{
// Minimal pacing (optional)
delay(5);
}
void dump(uint32_t from, uint32_t to)
{
for (uint32_t i = from; i < to; i++) // I2C_DEVICESIZE_CAT24M01
{
volatile int x = ee.readByte(i);
char buffer[24];
if (i % 16 == 0)
{
char buffer[24];
dbg->print('\n');
#if defined(ESP8266) || defined(ESP32)
sprintf(buffer, "%08X\t", i); // ESP cast (long unsigned int)
#else
sprintf(buffer, "%08lX\t", i); // AVR needs lX
#endif
dbg->print(buffer);
}
sprintf(buffer, "%02X\t", x);
dbg->print(buffer);
}
dbg->println();
}
void test(uint32_t offset)
{
dbg->println(F("\n[TEST] Sequential 10-byte write/read verification"));
dbg->print(F("[TEST] Start offset: "));
dbg->println(offset);
dbg->print(F("[TEST] Page index: "));
dbg->println(offset / 256);
dbg->print(F("[TEST] Page offset in page: "));
dbg->println(offset % 256);
if ((offset % 256) + 10 > 256)
{
dbg->println(F("[WARN] Sequence crosses a 256-byte page boundary (multi-byte page writes would need splitting)."));
}
dbg->println(F("[TEST] Writing bytes (value = index)"));
for (uint8_t i = 0; i < 10; i++)
{
uint32_t addr = offset + i;
uint8_t value = i;
dbg->print(F("[WRITE] addr="));
dbg->print(addr);
dbg->print(F(" value="));
dbg->print(value);
dbg->print(F(" (0x"));
dbg->print(value, HEX);
dbg->println(')');
ee.writeByte(addr, value);
delay(5); // modest pacing for EEPROM internal write cycle
}
dbg->println(F("\n[TEST] Reading back and verifying"));
uint8_t errors = 0;
for (uint8_t i = 0; i < 10; i++)
{
uint32_t addr = offset + i;
uint8_t expected = i;
uint8_t got = ee.readByte(addr);
dbg->print(F("[READ] addr="));
dbg->print(addr);
dbg->print(F(" got="));
dbg->print(got);
dbg->print(F(" (0x"));
dbg->print(got, HEX);
dbg->print(')');
dbg->print(F(" expected="));
dbg->print(expected);
if (got == expected)
{
dbg->println(F(" [OK]"));
}
else
{
dbg->println(F(" [FAIL]"));
errors++;
}
delay(5);
}
dbg->print(F("[RESULT] Errors: "));
dbg->println(errors);
if (errors == 0)
{
dbg->println(F("[RESULT] All 10 bytes verified successfully."));
}
else
{
dbg->println(F("[RESULT] Verification failed. Investigate I2C integrity or EEPROM wear/state."));
}
dbg->println();
}Debug Message
Using:
build_flags =
-O3
-DCORE_DEBUG_LEVEL=5
ESP-ROM:esp32s2-rc4-20191025<CR>
Build:Oct 25 2019<CR>
rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT)<CR>
SPIWP:0xee<CR>
mode:DIO, clock div:1<CR>
load:0x3ffe5110,len:0x1174<CR>
load:0x4004a000,len:0x8d8<CR>
load:0x4004e000,len:0x3324<CR>
entry 0x4004a138<CR>
[ 1][D][esp32-hal-tinyusb.c:825] tinyusb_enable_interface2(): Interface CDC enabled<CR>
[ 10][D][esp32-hal-tinyusb.c:703] tinyusb_load_enabled_interfaces(): Load Done: if_num: 2, descr_len: 75, if_mask: 0x10<CR>
[ 23][I][esp32-hal-psram.c:104] psramAddToHeap(): PSRAM added to the heap.<CR>
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide
- I confirm I have checked existing issues, online documentation and Troubleshooting guide.