Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLE on the ESP32-S3 causes CircuitPython to hard fault under certain conditions #9708

Open
gingershaped opened this issue Oct 10, 2024 · 2 comments
Assignees
Labels
ble bug espressif applies to multiple Espressif chips
Milestone

Comments

@gingershaped
Copy link

CircuitPython version

Adafruit CircuitPython 9.2.0-beta.0-33-g52602caae4-dirty on 2024-10-10; Adafruit Camera with ESP32S3

Code/REPL

# See https://gist.github.com/gingershaped/d0336649c3da9f89775b22fcb78ea451

Behavior

Under specific conditions, connecting to the Memento board over Bluetooth Low Energy causes CircuitPython to hard fault and enter safe mode. Usually it happens after doing some variation on these steps:

  1. put this code in ctstest.py
  2. put import supervisor; supervisor.runtime.ble_workflow = False in boot.py
  3. reset the board
  4. enter the REPL
  5. import ctstest
  6. attempted to connect with my phone; Android's pairing dialog appeared but the program produced this error:
advertising
connected
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ctstest.py", line 37, in <module>
  File "adafruit_ble/__init__.py", line 143, in pair
_bleio.BluetoothError: Unknown system firmware error: 2

nonetheless, my phone paired to it
7. import ctstest again; my phone automatically connects to it, even though I passed bond=False to pair(), and it produces a different error:

advertising
connected
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ctstest.py", line 37, in <module>
  File "adafruit_ble/__init__.py", line 143, in pair
ConnectionError: Connection has been disconnected and can no longer be used. Create a new connection.
  1. import ctstest again; this causes a hard fault

If my phone is able to pair, the board will occasionally show BLE:Reconnecting in the top status bar when it enters safe mode after faulting; when this happens, resetting the board will continue to show BLE:Reconnecting (instead of BLE:Off as would be expected) and running ctftest again causes it to stall on the call to pair when attempting to connect to it with my phone, and calling _bleio.adapter.erase_bonding() makes pair work again even though ctftest explicitly passes bond=False to pair.

Description

No response

Additional information

The phone I have is a Google Pixel 6a. The vanilla CircuitPython build for the Memento does not have _bleio enabled, I'm using a modified version which includes it.

@dhalbert dhalbert added this to the 9.2.0 milestone Oct 11, 2024
@dhalbert dhalbert added espressif applies to multiple Espressif chips ble labels Oct 11, 2024
@dhalbert dhalbert self-assigned this Oct 14, 2024
@dhalbert
Copy link
Collaborator

I was able to reproduce the firmware error: 2 easily. I have not yet tried to reproduce the crash in earnest.

Some observations on the code:

Error2 is EALREADY, that is, pairing is already in progress. You do not need to call .pair() yourself, because pairing is being initiated by the Android central, when it brings up the "Pair?" dialog box. If I run the same program on an nRF board with CircuitPython, I get an "invalid state" error, which I think is trying to indicate the same thing: you're not in a state where you can initiate pairing, because pairing is already underway.

So just spin until .paired is True, if you want to wait for that. In my test I did:

        while not connection.paired:
            print("checking pairing")
            time.sleep(1)

Also note that the rest of the code:

        dis = connection[DeviceInfoService]
        print(dis.manufacturer)
        print(dis.model_number)

doesn't work, because the connection is not going the resolve the central's (the phone's) DeviceInfoService. If you, as a peripheral, want to use services provided by the central, you use a SolicitServicesAdvertisement. See this as an example: https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/main/examples/ble_current_time_service.py

By the way the bond argument doesn't do anything, either on nRF or Espressif. It seems to be aspirational only, and I'm going to check into that further.

It is of course the case that we should not crash, and so I will keep this issue open. I think that the previous errors are getting BLE into a bad state in some way, and we are assuming something about the state that we shouldn't be.

@gingershaped
Copy link
Author

gingershaped commented Oct 16, 2024

Error2 is EALREADY, that is, pairing is already in progress.

I think this should have a more useful error message than "unknown system firmware error", if it's so easily triggerable.

Also note that the rest of the code doesn't work

I based my code off of the device info example, so it would probably be a good idea to update that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ble bug espressif applies to multiple Espressif chips
Projects
None yet
Development

No branches or pull requests

2 participants