i2c+timer+work keeps getting -22 or -128 and keep crashing


I am using i2c to get sensor data. At first the client write a value to the service. In the service on write callback it trigger's a timer, in the timer, it submit a work. In the work handler, it reads data and then notify the client.

but the notify keeps returning -22 or -128, the bluetooth is connected, and the notify data is correct.

When the client disconnect, the chip crashed and auto restarted.

How should I fix this?


  • Hi 

    Why do you use a timer to trigger the work item, do you need to add a delay to the sensor readout? 

    Is the notification ever successful, or will it always return an error? 

    Have you tried to debug the call to gatt_notify(..) so you can see exactly where in the code the error is returned? 
    That can usually provide more details than the error code alone. 

    Would you be able to share the code showing how the sensor is read and the notification sent? 

    Best regards

  • Hi,

    I use timer in order to get sensor data periodically, which actually I learned from here:  Zephyr Timer + I2C 

    the notification does succeed once after the client disconnect once and then connect again.

    I am not be able to debug because the 52811 small RAM. Is there anyway that I can only debug ble part?

    My code is based on the zephyr/samples/sensor/lsm6dso, and the only change I made is send out sensor data calling bt_gatt_notify

    static inline float out_ev(struct sensor_value *val)
    return (val->val1 + (float)val->val2 / 1000000);

    static void float2byte(float value, uint8_t *out_data,int len)
    uint8_t *pdata = (uint8_t *)&value;
    for(int i = 0;i < len;i++)
    out_data[i] = *pdata++;

    const struct device *const mdev = DEVICE_DT_GET_ONE(st_lsm6dsr);

    static void fetch_and_display(const struct device *dev)

    struct sensor_value x, y, z;

    float xyz[3];
    uint8_t acc_data[12];


    /* lsm6dsr accel */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_ACCEL_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, &x);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Y, &y);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &z);

    xyz[0] = out_ev(&x);
    xyz[1] = out_ev(&y);
    xyz[2] = out_ev(&z);
    printf("accel x:%f ms/2 y:%f ms/2 z:%f ms/2\n",
    xyz[0], xyz[1], xyz[2]);



    // printf("accel x:%f ms/2 y:%f ms/2 z:%f ms/2\n",
    // out_ev(&x), out_ev(&y), out_ev(&z));

    /* lsm6dsr gyro */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_X, &x);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_Y, &y);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &z);

    printf("gyro x:%f rad/s y:%f rad/s z:%f rad/s\n",
    out_ev(&x), out_ev(&y), out_ev(&z));

    printf("trig_cnt:%d\n\n", trig_cnt);

    int bt_set_sensor_data(uint8_t * p_data,uint16_t len)
    int rc;
    // printk("len: %d\n",len);
    // for(int i=0;i<len;i++){
    // printk("data[%d]=0x%d\n",i,p_data[i]);
    // }
    rc = bt_gatt_notify(mconn, &cube_svc.attrs[1], p_data, len);
    printk("rc: %d\n",rc);

    return rc == -ENOTCONN ? 0 : rc;


  • To be more specific, the current issue is: after the 1st connect, the sensor data notify got -22. then the client disconnect, disconnect working fine. the client connect again, the sensor data notify successfully. but when client disconnect again, the chip crashed and auto restart. 

    In a summary, 1st connect, can't notify, but can disconnect. 2nd and later, can notify, but disconnect crash the chip.

    I set the CONFIG_BT_LOG_LEVEL_DBG = y, but no any errors info.


  • Thank you for your sharing. It’s great that the problem is finally fixed.

    skibidi toilet

  • no its not fixed. the problem is still there: 1st connect, can't notify, but can disconnect. 2nd and later, can notify, but disconnect crash the chip.