Skip to content

Hard fault with BLE and Async IO #10515

@daniel-alsen

Description

@daniel-alsen

CircuitPython version and board name

Adafruit CircuitPython 10.0.0-beta.0-8-g857c625421-dirty on 2025-07-25; Adafruit Feather ESP32S3 4MB Flash 2MB PSRAM with ESP32S3

Code/REPL

import time
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services import Service
from adafruit_ble.characteristics import Characteristic
from adafruit_ble.characteristics.json import JSONCharacteristic
from adafruit_ble.uuid import StandardUUID
from asyncio import sleep as async_sleep 
from asyncio import create_task, run as async_run, sleep as async_sleep

ble_service = None
advertisement = None
ble_connection = None
ble_connected = False

# Setup BLE
def setup_ble():
    global ble_connection, advertisement, ble_service
    try:
        # Setup BLE
        print("Setting up BLE connection...")
        ble_connection = BLERadio()
        
        # Create advertising name
        advertising_name = "MyDevice"
        ble_connection.name = advertising_name
        
        # Create a BLE-advertisement
        print("Creating BLE Service...")

        ## !! The code hangs/crashes here sometimes, I got "Object has been deinitialized and can no longer be used. Create a new object." 2-3 times, but often not
        ble_service = MyService()
        
        print("Creating BLE Service Advertisement...")
        advertisement = ProvideServicesAdvertisement(ble_service)
        advertisement.connectable = True
        advertisement.complete_name = advertising_name

    except Exception as e:
        print(f"Failed to setup BLE: {e}")
        return

# Connect BLE
async def connect_ble():
    global ble_connection, advertisement, ble_connected

    # Update characteristics
    def update_characteristics():
        if ble_service and ble_connection.connected:
            
            # Update temperature characteristic
            ble_service.A = {
                "device": {
                    "message_type": "A",
                    "device_id": "12345",
                    "data": float(10.4)
                }
            }
    
    # Loop to handle BLE connection & status updates
    previous_connected = ble_connection.connected

    try:
        print(f"Starting BLE advertising...")
        if ble_connection and advertisement:
            ble_connection.stop_advertising()
            ble_connection.start_advertising(advertisement)
            print(f"Advertising started: {ble_connection.advertising}")
        else:
            print("BLE connection or advertisement not initialized, cannot start advertising")
            return
        
        while True:
            current_connected = ble_connection.connected
            
            if previous_connected != current_connected:
                if current_connected:
                    # Handle connection
                    print("BLE connected")
                    ble_connected = True
                else:
                    # Handle disconnection
                    print("BLE disconnected") 
                    ble_connected = False
                    if ble_connection and advertisement:
                        ble_connection.stop_advertising()
                        ble_connection.start_advertising(advertisement)
                
                previous_connected = current_connected  # Update previous state
            
                # Check for notification flags and update characteristics
                if ble_connection.connected and ble_service:
                    update_characteristics()
            
            await async_sleep(0.1)
            
    except Exception as e:
        print(f"BLE exception: {e}")

class MyService(Service):
    uuid = StandardUUID(0x181C)
    
    # Characteristics
    A = JSONCharacteristic(
        uuid=StandardUUID(0x2A5A),
        properties=Characteristic.READ,
    )
    B = JSONCharacteristic(
        uuid=StandardUUID(0x2A5B),
        properties=Characteristic.READ,
    )
    C = JSONCharacteristic(
        uuid=StandardUUID(0x2A5C),
        properties=Characteristic.READ,
    )
    D = JSONCharacteristic(
        uuid=StandardUUID(0x2A5D),
        properties=Characteristic.READ,
    )
    E = JSONCharacteristic(
        uuid=StandardUUID(0x2A5E),
        properties=Characteristic.READ,
    )
    F = JSONCharacteristic(
        uuid=StandardUUID(0x2A5F),
        properties=Characteristic.READ,
    )
    G = JSONCharacteristic(
        uuid=StandardUUID(0x2A60),
        properties=Characteristic.READ,
    )
    H = JSONCharacteristic(
        uuid=StandardUUID(0x2A61),
        properties=Characteristic.READ,
    )
    I = JSONCharacteristic(
        uuid=StandardUUID(0x2A62),
        properties=Characteristic.READ,
    )
    
    J = JSONCharacteristic(
        uuid=StandardUUID(0x2A6A),
        properties=Characteristic.WRITE,
    )
    K = JSONCharacteristic(
        uuid=StandardUUID(0x2A6B),
        properties=Characteristic.WRITE,
    )
    L = JSONCharacteristic(
        uuid=StandardUUID(0x2A6C),
        properties=Characteristic.WRITE,
    )
    M = JSONCharacteristic(
        uuid=StandardUUID(0x2A6D),
        properties=Characteristic.WRITE,
    )
    N = JSONCharacteristic(
        uuid=StandardUUID(0x2A6E),
        properties=Characteristic.WRITE,
    )
# Startup
try:
    time.sleep(0.1)
    setup_ble()
    time.sleep(0.1)

except Exception as e:
    print(f"Exception during startup: {e}")

# Main loop
async def main():
    try:
        create_task(connect_ble())
        while True:
            await async_sleep(0.1)
    except Exception as e:
        print(f"Main loop exception: {e}")
        
async_run(main())

Behavior

Intermittent hard fault / crash or code hangs and then crashes after a few seconds. This happens when creating a BLE service (see comment), or at later stages when reading characteristics or connecting / disconnecting. Often with no messages as all.

Intermittent exception message during creation of BLE service: "Object has been deinitialized and can no longer be used. Create a new object."

Description

This minimal code sample hangs during service creation on my board. But the behaviour can be different as it's integrated in more complex code, then the code can crash at a later stage or not at all for a while.

Additional information

Hints for debugging:

What defines how many characteristics a BLE service can have? Micropython Pycom Forum - jmarcelino 3 Feb 2017 - You need to use the nbr_chars parameter when you create a service. For example, with two characteristics, that would be: serv = ble.service(uuid=b'1111', isPrimary=True, nbr_chars=2. This was added in 1.5.0.b1.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions