Repository navigation
I2C disconnects BLE #58
Description
Activity
sorry, i realized i should probably be a little more specific:
when trying to transmit BLE packets and read/write I2C simultaneously, the whole microcontroller hangs for a few seconds and the BLE connection (to the central) fails. If using I2C without also transmitting BLE packets, the connection appears to survive.Well BLE for WB using shared mem and IRQ. Lot of
__disable_irqare used in the sharedmem.
As I don't have your code and based on your inputs, it is not a good idea to perform "simultaneously" BLE action and I2C read as I2C is based on IT.i know 'simultanious' is not really true on this kind of semi-single-core microcontroller, but how does one check whether the BLE packets have all finished transmitting? (I am using https://github.com/thijses/Arduino-HardwareBLESerial which is (a fork of) a library that just blasts serial data (for easy debugging) over 20-byte BLE packets. This library uses the (legacy(?)) characteristic.setValue(), which refers to writeValue(). Is there a function i can use to wait until all the data in the transmit buffer is successfully transmitted? (or am i fundamentally misunderstanding how the HCI connection to the coprocessor works?)
Could you share your full code. Core version, STM32duinoBLE version, STM32WB Copro Wireless Binary version. I gues your board is the Nucleo WB55?
yes, of course (sorry):
Copro stack: stm32wb5x_BLE_HCILayer_fw.bin version 1.16.0
platformIO details:
PLATFORM: ST STM32 (15.4.1) > P-Nucleo WB55RG
HARDWARE: STM32WB55RG 64MHz, 192KB RAM, 512KB Flash
PACKAGES:- framework-arduinoststm32 @ 4.20200.221104 (2.2.0)
- framework-cmsis @ 2.50700.210515 (5.7.0)
- toolchain-gccarmnoneeabi @ 1.90201.191206 (9.2.1)
i was using STM32duinoBLE version 1.2.3, but i just tested and 1.2.4 shows the same behaviour
the whole code is excessively large for this question, and technically under NDA. But i'll scrap together some minimal code to reproduce the issue on my end (not that you could actually repeat the hardware without the I2C devices on my PCB).
right now i have to go, but i'll be back in a few days to test some more (i just remembered BLE.debug() exists)
Pio uses an old version of the core and we do not support it. WB cube and the stack used here are not aligned.
first of all, thank you for your continued patience;
- I'm now running the latest STM32 arduino framework, directly from https://github.com/stm32duino/Arduino_Core_STM32
(P.S. pio is strange, they are indeed several releases behind, for reasons unbeknownst to me) - STM32duinoBLE is still on 1.2.4
The issue still persists, but i've got some more hints,
now that i've actually enabled BLE.debug(Serial):edit: turns out NDEBUG was not defined, BLE.debug() was still disabled. When i enable BLE.debug() as well, it crashes when it has to transmit anything demanding over BLE. I'll just stick to 1 debug mode at-a-time for now.
When it crashes (during extended I2C tests, while it's also trying to print something to the bleSerial (so presumably some packets are still queued up for transmission), it hangs for several seconds, then it printed the following (unique) debug line:
ble evt: 0x05 payload: 00 01 08 08
mm evt released: 0x05 buffer addr: 0x20030030edit: after enabling BLE.debug() (instead of undefining NDEBUG), it spits out the following:
HCI EVENT RX <- 04050400010808
HCI COMMAND TX -> 010A200101
HCI EVENT RX <- 0413050101080100
HCI EVENT RX <- 0413050101080100
HCI EVENT RX <- 0413050101080100
HCI EVENT RX <- 0413050101080100
HCI EVENT RX <- 040E04010A2000
HCI ACLDATA TX -> 0201081B00170004001B0E006D70200920493243657272436F756E7465723A20I tried to find what evtcode 0x05 represents, but i think i may be a little out of my depth already. Is it possible that the I2C peripheral code uses similar event (software interrupt?) handlers, but that they overlap, and so the BLE event catcher accidentally caught some of the I2C events (or vice versa)? (truly a guess, not even remotely educated)
on a completely unrelated note; the links in
src/utility/STM32Cube_FW/README.mdare broken, because there's 3 'v's instead of 1 (in multiple places). I noticed that in an earlier release (1.15.0) there were also 2 'v's instead of 1.- I'm now running the latest STM32 arduino framework, directly from https://github.com/stm32duino/Arduino_Core_STM32
little update:
i have made some small steps towards understanding the inner-workings of the STM32duinoBLE code. There's a few callbacks, buffers and abstraction layers to get through, but in HCI.cpp a lot of the important stuff is revealed.
stuff like:#define EVT_DISCONN_COMPLETE 0x05 #define EVT_NUM_COMP_PKTS 0x13which answers my questions about that the eventcodes mean, which is nice. Unfortunately, evtcode 0x05 is just a disconnection, which doesn't really help me identify why it disconnects. However, after following the path of the 0x13 evtcode, i found
_pendingPkt.
This handy variable allows me to wait for BLE packets to be 100% done transmitting before doing I2C interactions (to avoid interrupt overlap).However, this did NOT solve my problem :( , it seems that simply the act of doing ~100 I2C read/writes in rapid succession (during a time when the HCI is quiet) causes the BLE to die. I'm not sure whether the act of sending another BLE packet after the I2C stuff is what triggers the disconnect, or if that's just how the disconnect is discovered. Either way, there must be some deeper issue than just competing interrupts.
on a completely unrelated note; the links in
src/utility/STM32Cube_FW/README.mdare broken, because there's 3 'v's instead of 1 (in multiple places). I noticed that in an earlier release (1.15.0) there were also 2 'v's instead of 1.Thanks, missed that, I' fix it and updated the script which update it automatically: stm32duino/Arduino_Core_STM32@2e75489
About your issue I have no clue and will not have time soon to try to reproduce nor debug.
As stated, my first thought was an issue with IRQ which block BLE and probably disconnect it as it considered not maintained or something similar.absolutely understandable, and no problem.
I'm going to continue digging for the true cause of the issue (which, may well be hardware after all). If i find something definitive, i'll let you know.Reacted by Frederic Pillon and HenrydwHi @thijses
Withotu code to reproduce, it's hard to help. Always think it is linked to irq management.
Could you test with new STM32duinoBLE version, please?i'll try to do some quick testing next week (probably wednesday)
Reacted by Frederic Pillonshort answer; yes, the issue appears to persist.
But i'm tempted to just blame my code at this point.
My whole code is bulky, technically confidential (and not very well-written, so) i'm not posting it here.
The snippit of code where the faillure happens is not huge though;
Similar to the LedControl.ino example, i open a simple connection:BLEDevice central = BLE.central(); if (central) { while (central.connected()) { checkForCommands(); // check if the user has input any commands in the serial terminal if (switchCharacteristic.written()) { // if the remote device wrote to the characteristic, use the received value to control the LED: bool newLEDstatus = switchCharacteristic.value() != 0; // any value other than 0 digitalWrite(debug_LED_green, newLEDstatus ? debug_LED_ACTIVE : !debug_LED_ACTIVE); // update LED state } // if-statement } // while-loop } // if-statementconnection works fine, LED toggles quickly and reliably, untill
checkForCommands()starts doing a whole bunch of blocking I2C read/writes.
Replacing the I2C function with delay(1000); does not kill the connection, so i don't think it's just a blocking function that kills BLE.
Similarly, doing only a few (<10) read/writes consistantly makes BLE slow down (packets take 1~2 seconds to arrive if sent during/shortly-after I2C stuff), and occaisionally kills BLE (connection timeout on phone side, MCU side sometimes recognises disconnect).
The I2C code is also needlessly long, but it boils down to just:for(uint16_t i=0; i<packetLossTestCount; i++) { Wire.beginTransmission(slaveAddress); Wire.write(registerToRead); Wire.endTransmission(); Wire.requestFrom(slaveAddress, bytesToRead); for(uint8_t i=0; i<bytesToRead; i++) { readBuff[i] = Wire.read(); } } // for-loopusing an unmodified, bog-standard
#include <Wire.h>lib from stm32duino/Arduino_Core_STM32, initialized to 100kHz (before BLE connection was made)
The versions of stuff i'm using are:- STM32duinoBLE 1.3.7 (according to library.properties)
- Arduino Code STM32 2.10.1 (i think)
(i am blissfully ignorant, i just let platformIO pull the latest packages like:
platform = ststm32 platform_packages = framework-arduinoststm32 @ https://github.com/stm32duino/Arduino_Core_STM32 ; pio package is out of date. This one includes required build script lib_deps = https://github.com/stm32duino/STM32duinoBLE ; for BLE board = nucleo_wb55rg_p framework = arduino build_flags = -D NDEBUG ; disables extra (BLE) debug
Using the STM32WB55, using I2C (especially using it frequently/intensively) will disconnect BLE devices, and sometimes even crash the whole microcontroller. Presumably, this is caused by an overbearing HAL_LOCK or interrupt disable in the I2C libraries (twi.h refers back to stm32wbxx_hal_i2c.h). PRINT_IPCC_INFO does not print anything when it disconnects. Is there an immediately obvious way to solve/debug this? I was hoping to avoid getting into the low-level stuff with the STM platform, but i suspect i might need to in order to find this one.