espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.89k stars 7.08k forks source link

Bluetooth affects I2C packets (IDFGH-6103) #7781

Open dizcza opened 2 years ago

dizcza commented 2 years ago

Environment

Problem Description

Dear ESP devs,

I have trouble with Bluetooth classic packets affecting I2C data read from an SDP31 Sensirion differential pressure sensor.

If Bluetooth is not started (not built in the binary file), no issues happen: the SDP31 sensor was running 10 hours straight without a problem. When Bluetooth is started (acceptor mode), either sending or receiving data causes the I2C SDA line (that connects SDP31 to the board) to output unrealistic values, and the sensor sends wrong CRC values, that is the I2C data have been corrupted. By the Bluetooth.

Old description An SDP sensor is a differential pressure sensor that measures the pressure difference between two open ports located 5 mm from each other. It outputs integers that should be divided by 60 to convert to Pa. When Bluetooth is active, every 10 seconds or so, I constantly see values 129 / 60 Pa or 255 / 60 Pa, or 256 / 60 Pa that my sensor outputs in a salient environment. These are huge pressure values of a range of 100+ dB. Such pressure difference could not happen in still air. If I close these two ports of the SDP31 sensor with a finger, meaning that the pressure difference *is* zero, the issue persists - I still see these unrealistic huge pressure differences read from the I2C line. These magic numbers - 111, 129, 255, and 256, - happen due to Bluetooth affecting I2C data read from a sensor. ~~The issue may be a sensor-specific one... I don't know.~~ Others have confirmed the issue.

In summary,

Bluetooth: bluedroid classic.

Expected Behavior

No warning logs with differential pressure values greater than 60 (1 Pa) are shown*.

*When the output value is greater than 60, the CRC does not much (not shown in the code for clarity).

Actual Behavior

I (1280) SPP_ACCEPTOR_DEMO: ESP_SPP_INIT_EVT
I (1290) SPP_ACCEPTOR_DEMO: ESP_SPP_START_EVT
I (1300) SPP_ACCEPTOR_DEMO: event: 10
I (1310) SDPSensor: I2C0 SDP Sensor initialized
I (1310) SDPSensor: SDPSensor_Reset ESP_OK
I (1330) SDPSensor: SDPSensor_StartContinuous ESP_OK
W (21570) BT_APPL: new conn_srvc id:26, app_id:255
I (21580) SPP_ACCEPTOR_DEMO: ESP_SPP_SRV_OPEN_EVT
W (38540) SDPSensor: DP 111
W (38570) SDPSensor: DP 111
W (40820) SDPSensor: DP 111
W (44950) SDPSensor: DP 111
W (191630) SDPSensor: DP 255
...

Code to reproduce this issue

To demonstrate the issue, I took the bt_spp_acceptor demo and modified the main file as follows:

Code to reproduce ```c static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) { static uint8_t buf_tx[1000]; switch (event) { case ESP_SPP_INIT_EVT: ESP_LOGI(SPP_TAG, "ESP_SPP_INIT_EVT"); esp_spp_start_srv(sec_mask,role_slave, 0, SPP_SERVER_NAME); break; case ESP_SPP_START_EVT: ESP_LOGI(SPP_TAG, "ESP_SPP_START_EVT"); esp_bt_dev_set_device_name(EXAMPLE_DEVICE_NAME); esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); break; case ESP_SPP_WRITE_EVT: if (param->write.status == ESP_SPP_SUCCESS) { if (param->write.cong) { esp_spp_write(param->write.handle, sizeof(buf_tx), buf_tx); } } break; case ESP_SPP_SRV_OPEN_EVT: ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT"); esp_spp_write(param->write.handle, sizeof(buf_tx), buf_tx); break; default: break; } } /** * @brief I2C SDP sensor master initialization */ static void i2c_sdpsensor_init(void) { int i2c_master_port = 0; int intr_flag_disable = 0; /* I2C master doesn't need buffer */ size_t i2c_master_rx_buf_disable = 0; size_t i2c_master_tx_buf_disable = 0; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = 19, .scl_io_num = 23, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = 400000, /*!< I2C master clock frequency */ }; ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &conf)); ESP_ERROR_CHECK( i2c_driver_install(i2c_master_port, conf.mode, i2c_master_rx_buf_disable, i2c_master_tx_buf_disable, intr_flag_disable)); ESP_LOGI("SDPSensor", "I2C0 SDP Sensor initialized"); } esp_err_t SDPSensor_StartContinuous() { uint8_t cmd[2] = { 0x36, 0x1E }; esp_err_t err = i2c_master_write_to_device(0, 0x21, cmd, 2, pdMS_TO_TICKS(100)); ESP_LOGI("SDPSensor", "SDPSensor_StartContinuous %s", esp_err_to_name(err)); // wait for sensor to start continuously making measurements vTaskDelay(pdMS_TO_TICKS(20)); return err; } esp_err_t SDPSensor_Reset() { uint8_t cmd[1] = { 0x06 }; const TickType_t ticks_to_wait_long = pdMS_TO_TICKS(100); esp_err_t err = i2c_master_write_to_device(0, 0x00, cmd, 1, ticks_to_wait_long); ESP_LOGI("SDPSensor", "SDPSensor_Reset %s", esp_err_to_name(err)); vTaskDelay(pdMS_TO_TICKS(20)); return err; } esp_err_t SDPSensor_ReadContinuousRaw(int16_t *diff_pressure_raw) { uint8_t data[2] = { 0 }; esp_err_t err = i2c_master_read_from_device(0, 0x21, data, 2, 0); if (err == ESP_OK) { *diff_pressure_raw = ((int16_t) data[0]) << 8 | data[1]; } return err; } static void sdptask_read_sensor() { int16_t dp; while (1) { esp_rom_delay_us(1000); if (SDPSensor_ReadContinuousRaw(&dp) == ESP_OK) { if (dp > 60) { ESP_LOGW("SDPSensor", "DP %d", dp); } } } } void app_main(void) { // the code from bt_spp_acceptor is here ... i2c_sdpsensor_init(); SDPSensor_Reset(); SDPSensor_StartContinuous(); // the core id on which to run the task does not matter xTaskCreatePinnedToCore(sdptask_read_sensor, "read_sensor", 2048, NULL, 1, NULL, APP_CPU_NUM); } ```
RFgermany commented 2 years ago

I can confirm the issue on my ESP32-C3-WROOM-02. IDF versions: 4.3 and latest Master. Custom PCB I also experience I2C problems when running Bluetooth. Every now and then, the stop bit is not being send. No Bluetooth, no I2C Problems.

iltis42 commented 1 year ago

I have the same issue on when Bluetooth is connected with my custom ESP32 board. Using v4.4 there are sporadically something like every 5 minutes false data bytes readout. With esp-idf v4.3 it's okay, no single false data readout, so IMHO the issue must have come in since IDF v4.4.

Normally the readouts of my barometric pressure sensor are around ce68ae (hex), then suddenly there is a reading "68fa80", what assumed that bytes are shifted by one to the left, the leading "ce" is missing causing a large delta of more than 10 Mio and an out of bounds (OOB) warning from my code that checks for that condition.

I (00:10:43.097) SPL06-007.cpp: P:ffce68ae,-3250002 T:0220fa PC:992.324635 T:33.386227 I2C E:0 I (00:10:43.196) SPL06-007.cpp: P:ffce6864,-3250076 T:0220fa PC:992.328891 T:33.386463 I2C E:0 I (00:10:43.297) SPL06-007.cpp: P:ffce68aa,-3250006 T:0220fa PC:992.324929 T:33.386700 I2C E:0 I (00:10:43.398) SPL06-007.cpp: P:ffce68da,-3249958 T:0220fa PC:992.322222 T:33.386936 I2C E:0 I (00:10:43.497) SPL06-007.cpp: P:ffce68da,-3249958 T:0220fa PC:992.322254 T:33.387169 I2C E:0 W (00:10:43.597) SPL06-007.cpp: P TE raw delta OOB: 6879872 68fa80 last: -3249958 ffce68da, delta 10129830 I (00:10:43.598) SPL06-007.cpp: P:68fa80,6879872 T:0220fa PC:279.777524 T:33.387398 I2C E:0 W (00:10:43.605) BMPVario.cpp: TE sensor delta OOB: 939.505766 m W (00:10:43.696) SPL06-007.cpp: P TE raw delta OOB: -3250002 ffce68ae last: 6879872 68fa80, delta 10129874 I (00:10:43.697) SPL06-007.cpp: P:ffce68ae,-3250002 T:0220fa PC:992.324828 T:33.387623 I2C E:0 I (00:10:43.797) SPL06-007.cpp: P:ffce68ae,-3250002 T:0220fa PC:992.324859 T:33.387848 I2C E:0

oursland commented 1 year ago

@dizcza @iltis42 Do you know if this is specific to an I2C port? Does the problem go away if you use I2C port 1?

dizcza commented 1 year ago

@oursland In fact, I tested on the I2C port 1. I didn't check port 0 though (and I cannot perform these tests right now).

iltis42 commented 1 year ago

Afaik both I2C ports were affected as the port is just an index in the software, and its not hardware related.

oursland commented 1 year ago

I am experiencing the issue on I2C port 0. I had hoped there was a hidden contention with the bluetooth subsystem that could be resolved by changing the I2C port, but it does not appear so.

iltis42 commented 1 year ago

Nope, i spent 30 hours to workaround this hence failed. There is no issue with latest version v4.3, but v4.4 is unusable when you need reliable I2C (!).

dizcza commented 1 year ago

@oursland My bad, I did test the device only on port 0. I didn't check port 1 at that time. Sorry for the confusion.

acf-bwl commented 1 year ago

We appear to have run into this issue as well. For us, the conflicting peripherals were the ledc (with associated interrupts) and uart. We are not using bluetooth. Unless both were enabled at the same time, the issue did not appear. We were trying to read a byte from the GPIO input register of a PCAL6416A I/O expander, and sporadically reading a zero byte instead of the correct value as appears on the wire once every few minutes. We spent many hours trying to find the issue in our code and hardware prior to finding this github issue. The problem reproduced for us on both 4.4.1 and 4.4.3. We were able to work around the problem by initializing the i2c interrupt from a task pinned to core 1.

AxelLin commented 1 year ago

Nope, i spent 30 hours to workaround this hence failed. There is no issue with latest version v4.3, but v4.4 is unusable when you need reliable I2C (!).

@iltis42 Can you reproduce the issue with latest v4.4.3 release? If yes, any chance to bisec the first bad commit in v4.4 branch?

grisharevzin commented 1 year ago

We have the same issue when CAN + Bluetooth + I2C are enabled at once. Random I2C corruptions (we're talking to a chip that uses a checksum on I2C transactions), about 0,1% of bytes arrive wrong. Disabling CAN makes it go away. Our workaround was to assign the CAN process to CPU0 and the I2C process to CPU1.

Development Kit: TTGO-T8-ESP32 Kit version: v1.7 Module or chip used: ESP32-D0WDQ6-V3 IDF version: toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch3 Build System: pio Operating System: Windows Using an IDE?: VSCode/pio. Flashing over JTAG with esp-prog. Power Supply: USB

iltis42 commented 1 year ago

Re: Can you reproduce the issue with latest v4.4.3 release? Yes Re: If yes, any chance to bisec the first bad commit in v4.4 branch? I had tried this, hence the older/intermediate revisions in 4.4 were not compatible/did not compile with my application that is quite huge usind a lots of features too including CAN, serial, bluetooth, WiFi and more. So unfortunately this wasn't feasible and i had to stick to the latest state to get a binary compiled and linked.

iltis42 commented 1 year ago

Our workaround was to assign the CAN process to CPU0 and the I2C process to CPU1.

So looks like a re-entrance issue. Some part of the code in v4.4 is not protected by a semaphore.

andrew-elder commented 1 year ago

I'm observing this issue with ESP-IDF 5.0.1. Is a fix in the works?

AxelLin commented 1 year ago

I'm observing this issue with ESP-IDF 5.0.1. Is a fix in the works?

I don't find any espressif people involved in this thread, so it's unlikely to have a fix.

CC @igrr

iltis42 commented 1 year ago

Dear espressif guy's. The problem is a major issue for I2C usage with ESP32, may it be possible to assign sm1 for a fix and increase a bit the prio (the issue is already in since quite some time). Thanks!

bldh commented 1 year ago

I have also encountered this issue. Running release v5.0.2 the data returned by the i2c driver will occasionally (multiple times per hour) have a different value than what was sent by the slave (confirmed by observing the transactions that return garbage data with an oscilloscope). The data does not appear to have any pattern to it that explains the fault.

Running the same code on esp-idf v4.3.5 has not returned a wrong value for 24 hours on two devices.

Running the same code on esp-idf v4.4.1 the issue occurs as it does on v5.0.2.

This issue appears to be related to commit 5986b204c6b608eb7b43005c4a44148ca2db2b24

Could someone please look into this, V4.3 of esp-idf goes end of life later this year and the issue is present in both v4.4 and v5.0.

bldh commented 1 year ago

I attempted to rollback the driver from V5.0.2 with the changes in the attached patch to see if the issue still occurs. i2c_driver_rollback.txt

The issue is still present after the patch so rolling back the driver is not the solution.

WatDavid commented 8 months ago

I also get wrong values over I2C when using BLE. Without BLE there are no I2C errors...

Is there still no fix for this? We need BLE and I2C in our Application on an ESP32 Wrover-E. With this bug we can´t trust the values received over I2C.