pkuzhx 发表于 2017-9-20 17:46:17

CSR8670 BLE多次连接失败后程序panic

我的8670是双模的,连接耳机后,会继续scan BLE设备。
而BLE设备发送的是定向广播,如果一个BLE设备匹配的是另外一个8670,那当前的8670可以scan到该BLE设备,但总是连接失败,于是就会反复scan,反复连接。
由于scan到的是ble_adv_event_connectable_directed类型的广播,所以8670会调用ConnectionSmGetAuthDevice函数去查找该设备是否在TDL中,这个函数反复调用多次以后,好像就把堆栈空间耗尽了。当再malloc的时候,就会失败,从而导致程序panic。
个人认为,函数调用过程中malloc的空间,最终都会合理释放掉,不断产生的消息的载荷,最终也都会释放掉,不明白为什么最后就把空间耗尽了?


附:最终产生panic的位置:
static td_data_t *tdl_find_device(
                        uint8                   addr_type,
                        const bdaddr            *addr,
                        uint16                  *pp,
                        uint16                  *pi
                        )
{
    td_data_t *td = (td_data_t *) PanicUnlessMalloc(SIZE_TD_DATA_T);
    one_slot *os = PanicUnlessNew(one_slot); /*每次都在这里panic,无可用空间分配了 */
    uint16 used = 0;
    uint16 pos;
    uint16 idx;
    uint16 max_trusted_devices = MAX_TRUSTED_DEVICES;
   
    read_trusted_device_index(&os->tdi);

    for (idx = 0;
         idx < max_trusted_devices && (pos = os->tdi.order) != TDI_UNUSED;
         idx++)
    {
      if (PsRetrieve(TRUSTED_DEVICE_LIST + pos, td, SIZE_TD_DATA_T))
      {
            os->dev_taddr.type = unpack_td_bdaddr(&os->dev_taddr.addr, td);

            if (
                os->dev_taddr.type == addr_type &&
                BdaddrIsSame(&os->dev_taddr.addr, addr)
                )
            {
                /* found our device */
                goto out;
            }

            /* mark slot as used */
            used |= 1 << pos;
      }
    }

    /* device data not needed anymore */
    free(td);
    td = NULL;

    if (idx < max_trusted_devices)
    {
      /* find first free slot */
      /* we do know that there is a free slot so no need for checking
         * idx < max_trusted_devices */
      for (pos = 0; used & (1 << pos); pos++);
    }
    else
    {
      /* tdl is full, return the last position */
      idx = max_trusted_devices - 1;
      pos = os->tdi.order;
    }

out:
    free(os);

    if (pp)
    {
      *pp = pos;
    }

    if (pi)
    {
      *pi = idx;
    }
   
    return td;
}


德王 发表于 2017-9-20 22:56:19

可以设置8670只是处理白名单中ble设备的广播

pkuzhx 发表于 2017-9-21 08:36:59

德王 发表于 2017-9-20 22:56
可以设置8670只是处理白名单中ble设备的广播

谢谢。
但是我需要经常更换和8670配对的BLE设备,所以scan→连接这个操作是必须要保留的,也必须可以处理白名单以外的新设备

德王 发表于 2017-9-21 09:02:19

ConnectionSmGetAuthDevice好像和ble无关
只是在ENABLE_SUBWOOFER/ENABLE_PEER才会用到

pkuzhx 发表于 2017-9-21 09:20:45

德王 发表于 2017-9-21 09:02
ConnectionSmGetAuthDevice好像和ble无关
只是在ENABLE_SUBWOOFER/ENABLE_PEER才会用到

嗯,ConnectionSmGetAuthDevice是一个通用函数,传统蓝牙和BLE连接时都会用到,就是看远程设备是否已经授权。
当然我的BLE部分其实也可以跳过这个函数:我只要收到合适的广播,不管他是什么类型,也不管有没有授权,反正去连接就好了,大不了就是连接失败而已。
但是例程中处理是要读取授权信息的,我也就照着做了。

pkuzhx 发表于 2017-9-21 09:22:35

void handle_ble_advertising_report(CL_DM_BLE_ADVERTISING_REPORT_IND_T * ind)
{
    switch(ind->event_type)
    {
      /* If connectable or discoverable, decide whether or not to connect the device */
      case ble_adv_event_discoverable:
      case ble_adv_event_connectable_undirected:
      {
            handle_ble_connectable_discoverable_adverts(ind);
      }
      case ble_adv_event_connectable_directed:
      {
            /* If the advertisement is from a paired device, request to connect it, otherwise ignore as pairing mode is not enabled */
            ConnectionSmGetAuthDevice(&theSink.rundata->bleInputMonitor.task, &ind->permanent_taddr.addr);            
      }
      break;
      case ble_adv_event_non_connectable:
      case ble_adv_event_scan_response:
      case ble_adv_event_unknown:
      {
            BLE_AD_DEBUG(("ble_adv_event_unknown\n"));
      }
      break;
    }
}

德王 发表于 2017-9-21 10:21:47

我用的 4.2 没有这些代码

pkuzhx 发表于 2017-9-21 10:52:45

德王 发表于 2017-9-21 10:21
我用的 4.2 没有这些代码

source是没有的。
我的BLE代码是从sink复制过来的……

德王 发表于 2017-9-21 15:19:18

sink ADK 4.2 也是没有的哦

pkuzhx 发表于 2017-9-22 08:19:16

德王 发表于 2017-9-21 15:19
sink ADK 4.2 也是没有的哦

不知道了,我是用的3.5版本……
页: [1] 2
查看完整版本: CSR8670 BLE多次连接失败后程序panic