This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Debugging techniques: adding custom profile/services

I've got something put together akin to the ble_lbs demo which uses a custom service. In fact, it's merely the LED part of that ble_lbs service, but on custom hardware. I can discover the device just fine, but the MCP log shows that it can't read the handle 0xB when it's going through the list of attributes.

I'm attaching the screenshot that shows the data returned from the discovery and the log data as well.

I'm not sure what the 0xB handle corresponds to. I'm also a bit fuzzy on what gets created automatically vs what you must specify when it comes to descriptors within a service. Any advice on debug techniques or common gotchas is helpful.

Thanks

MCP-errors.PNG

  • In general, I'd strongly recommend you to remove the reset from app_error_handler() and either uncomment the call to ble_debug_assert_handler() or insert an infinite loop of your own there, to make it easy to catch errors coming from the APP_ERROR_CHECK()s. This will enable you to halt with a debugger and inspect in which file and on which line things failed, making it much easier to find problems. You can also consider having a printf() before the infinite loop, to be able to easily log what's failing, even when not debugging.

    In your particular case, it could seem as if the device fails on something and then does a reset. When you use Master Control Panel, you can click through the attributes and see the handle for them right next to the UUID, above the value field. This should help you understand which attribute it can't read. However, beware that not all attributes have to be readable, so MCP not being able to read an attribute is not in itself a problem. In this case there seems to be some problem, since the link is lost right afterwards.

    One common gotcha when adding more services, if using the bond manager, is that you have to set the number of CCCDs in the bond manager configuration (ble_bondmngr_cfg.h), to make sure that buffers are sized correctly. The easiest way to count CCCDs is simply to use MCP. You don't have to take the Service Changed CCCD into account, so for the applicaiton from the screenshot, it would be sufficient to set BLE_BONDMNGR_CCCD_COUNT to 1.

    Edit: If the handle that fails reading is a CCCD, what happens is most likely that the application doesn't reply to the event BLE_GATTS_EVT_SYS_ATTR_MISSING. The softdevice will give this event to ask the application to supply CCCD values for the currently connected Central. If your application uses the bond manager, this is handled there, but if not, you'll have to make sure to reply in your application. By default, if you don't ever store any information about your peer devices, this can be done by a call like this in on_ble_evt() of main.c:

    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
    

    Adding a print of the events you get from the softdevice may often also be a useful debugging technique, to see what's going on.

  • In this case the firmware just keeps running. I have an app_error_handler that spins after disabling interrupts so that if I see the background task LED stop blinking I know that I've hit that handler. It seems like there is an event that's getting dropped somewhere, but I can't seem to figure it out. That or there's an inconsistency between what the device says it has (what the MCP sees) and what it really has.

    I think the only tool I have for this particular problem is inspection and trial-and-error. Unfortunately, I am also not a BLE expert so I also have to improve my understanding of the protocol in general.

  • When investigating another question, I stumbled upon a behavior that looked very much like this, so I just edited and expanded my reply a little. The other question was this, which may be of interest anyway: https://devzone.nordicsemi.com/index.php/ble_app_proximity-without-bond_manager

  • It seems there should be a way to determine which handle the 0xB corresponds to. I added the case that you mentioned, since it's in the ble_lbs app and my app was missing that. Aside: I really like the ble_lbs app, but it's written against the 4.4 SDK whereas I'm using the 5.x SDK. I ended up using the ble_lbs 4.4 app and the ble_hrs app from the 5.x SDK as my references, which has probably led to a poor mix-and-match result.

    At this point, I'm going to do some stepping through the initialization code and just map out what each handle corresponds to in the GATT table. I need to determine if 0xB is part of the custom service or something else. My guess is the former, but I want to be sure.

  • Did you read my initial reply? "When you use Master Control Panel, you can click through the attributes and see the handle for them right next to the UUID, above the value field. This should help you understand which attribute it can't read."

    Also, just yesterday I pushed an updated ble_app_lbs to our GitHub. You may want to take a look here: https://github.com/NordicSemiconductor/nrf51-ble-app-lbs An updated version of the application note itself should be available in the coming weeks.

Related