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

Hi,

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?

Thanks,

Parents
  • 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
    Torbjørn

  • 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];

    trig_cnt++;

    /* 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]);

    float2byte(xyz[0],acc_data,4);
    float2byte(xyz[1],acc_data+4,4);
    float2byte(xyz[2],acc_data+8,4);

    bt_set_sensor_data(acc_data,sizeof(acc_data)/sizeof(acc_data[0]));

    // 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;
    }

    Thanks,

Reply
  • 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];

    trig_cnt++;

    /* 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]);

    float2byte(xyz[0],acc_data,4);
    float2byte(xyz[1],acc_data+4,4);
    float2byte(xyz[2],acc_data+8,4);

    bt_set_sensor_data(acc_data,sizeof(acc_data)/sizeof(acc_data[0]));

    // 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;
    }

    Thanks,

Children
No Data
Related