Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

A Problem on Buttonless DFU + Bonding valid.

Currently, we are testing that 「buttonless DFU + Bonding valid」 in our App.

But After performing F / W Update with DFU, other BLE Service became invisible.(※2)

So, as a result of comparing the log of the Normal Project(No problem) with the log of the current problem project,

I found that there are the following differences.(In the normal case, the following events will occur.)

· PM_EVT_SERVICE_CHANGED_IND_CONFIRMED
· PM_EVT_PEER_DATA_UPDATE_SUCCEEDED

And Compared & checked "sdk_config.h", "makefile", "linkscript file", "source file", etc. But did not find a place likely to be a cause.

How can I solve this problem?

Why does the above log difference occur?

Please answer me about my question.

※ SDK Version

     nRF5_SDK_15.0.0_a53641a

※ IC

     nRF52832

※ Problem Project'SDK Config File

sdk_config.h

(※2)

<Before DFU Update>

      

<After DFU Update>

Parents
  • Hi Cerevo, 

     

    I suspect that the service changed characteristic was not included in either the application or the bootloader.

    I would suggest to turn off and on the iPhone and test again. 

     

    You mentioned  a "normal case" what was that ? Which firmware did you use when you have a normal case ? 

     

    Have you test and verify your new firmware actually has other services ? (test without bootloader, flash softdevice + application directly)

  • Hi Hung Bui,

    >I suspect that the service changed characteristic was not included in either the application or the bootloader.

    No, both Bootloader (DFU) and Application are defined and activated as follows.

    #define NRF_SDH_BLE_SERVICE_CHANGED 1

    > I would suggest to turn off and on the iPhone and test again.

    I tested it again, but it was the same result.

    > You mention a "normal case" what was that? Which firmware did you use when you have a normal case?

    I added Device Information Service based on "ble_app_buttonless_dfu" in example and tested it.

    This is OK, DIS (Device Information Service) is displayed even after F / W Update.

    > Have you test and verify your new firmware actually has other services ? (test without bootloader, flash softdevice + application directly)

    Yes, My Application includes "DIS", "Battery Service", and self-defined Service like the attached photo ("Before DFU Update").

    Of course, it is tested and there is no problem.

    So, you do not know why this problem happens after all?

  • ・「Did you do bonding  in your application and in your DFU bootloader ? If you do bonding, have you set NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS = 1  ? and use ble_dfu_bonded.c in your application code ?」

    Yes, of cource.No Problem.

    For Application,

    #define BLE_DFU_ENABLED 1

    #define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 1

    #define NRF_SDH_BLE_SERVICE_CHANGED 1

    I am defining it.

    In the case of DFU,

    #define NRF_BL_DFU_ENTER_METHOD_BUTTONLESS 1

    #define NRF_DFU_BLE_REQUIRES_BONDS 1

    #define NRF_SDH_BLE_SERVICE_CHANGED 1

    I am defining it.

    ・「The line you commented out checking if the service changed flag has been set or not. If it has been set, gatt_cache_manager.c will send a service changed indication to the iPhone and the iPhone will do a service discovery. By removing that check, you always request the phone to do service discovery, resulting in the full att table read by iPhone. 

    To get the flag set, you would need to call gscm_local_database_has_changed(). This is done inside ble_dfu_buttonless_bootloader_start_prepare(), if you set the NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS  flag correctly, it should be called before you switch to the bootloader. 」

    Yes, I already understand the above content.

    I also confirmed the contents of "ble_dfu_buttonless_bootloader_start_prepare ()".

    ・「Note that you need to make sure the flash is being updated properly before you switch to bootloader. 

    Yes, I do not think that writing to Flash eventually went well.
    However, as in the log of (★) below, Write to Flash was also Success.

    In the end, despite successfully writing to Flash correctly,
    Why does this problem occur?

    ========================LOG==================================
    0> <info> app: Writing peer data to the bootloader...
    0> <info> app: system attribute table len: 8
    0> <info> app: In ble_dfu_buttonless_bootloader_start_prepare
    0> <info> app: Device is preparing to enter bootloader mode.
    0> <info> app: Disconnected peer
    0> <info> app: peers_count 1
    0> <info> app: peer id 0
    0> <info> app: PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    0> <info> app: Updating Service Changed indication for peers, 0 left
    0> <info> app: Finished updating Service Changed indication for peers     <------★
    0> <info> app: Device will enter bootloader mode.
    0> <info> app: Start....
    0> <info> app: gpiote_init
    0> <info> app: button_init
    0> <info> app: initADPD153GGRI

  • You may need to dig deeper, and check on the first time booting up,after a DFU, would the new firmware be able to read the peer information data and get p_service_changed_pending = 1  ? or not. Maybe you put a break point in right after this printed out: Finished updating Service Changed indication for peers  , and check in flash if the data is written correctly. (you can simply dump the flash content to a hex and compare 2 hexes, before and after you trigger Start DFU) 

    You mentioned that you didn't have trouble when testing with the buttonless example ? 

    I assume you don't change attribute table or anything, simply DFU update the same firmware ?

     

  • Hi Hung Bui.

    ・「You may need to dig deeper, and check on the first time booting up,after a DFU, would the new firmware be able to read the peer information data and get p_service_changed_pending = 1  ? or not. 

    -->I Checked. it was p_service_changed_pending  = 0. 

    ・「Maybe you put a break point in right after this printed out: Finished updating Service Changed indication for peers  , and check in flash if the data is written correctly. (you can simply dump the flash content to a hex and compare 2 hexes, before and after you trigger Start DFU) 

    --> I did. But When comparing HEX Dump,Because i do not know the storage address (because it saved the data with pdb_raw_store), I could not identify the location of p_service_changed_pending.

    ・「I assume you don't change attribute table

    --> Thank you. I looked at this part. 

    After all, the cause was the definition of "NRF_SDH_BLE_GATT_MAX_MTU_SIZE".

    To increase the transfer speed, set the MTU size to I changed it from 23 to 247.

    When I restored it(247 -> 23),
    · PM_EVT_SERVICE_CHANGED_IND_CONFIRMED
    · PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    An event occurred. it's OK.

    By the way, I have the following questions so please check.
    1) First of all, why does this part cause this problem phenomenon?

    2) Next, in order to increase the transfer speed, I would like to maintain the MTU size as 247,
    How can I deal with it?

  • Hi Chan, 

     

    Thanks for updating us. 

    Could you confirm if you modify the buttonless dfu example in the SDK to have MTU size to 247, you see the same problem ? 

    If you can check that, we can reproduce the issue here and find out what could be the wrong. Which phone did you use ? 

  • Hi Hung.

    ・「Could you confirm if you modify the buttonless dfu example in the SDK to have MTU size to 247, you see the same problem ? if you can check that, we can reproduce the issue here and find out what could be the wrong.」

    --> I tested. Also in the buttonless dfu example, if you change the MTU size to 247, this problem occurs.
    I hope you test it out.

    Since the problem is reproducible, please let us know which part is the problem.

    Which phone did you use ? 

        I used iPhone X.

Reply
  • Hi Hung.

    ・「Could you confirm if you modify the buttonless dfu example in the SDK to have MTU size to 247, you see the same problem ? if you can check that, we can reproduce the issue here and find out what could be the wrong.」

    --> I tested. Also in the buttonless dfu example, if you change the MTU size to 247, this problem occurs.
    I hope you test it out.

    Since the problem is reproducible, please let us know which part is the problem.

    Which phone did you use ? 

        I used iPhone X.

Children
  • Hi Chan,

     

    I think we found the root cause of the issue. When you set the MTU to something else not the default that the iPhone set when connected, the nrf_ble_gatt.c will try to request sd_ble_gattc_exchange_mtu_request() immediately right after CONNECTED event. 
    This process will take some time, and if we call sd_ble_gatts_service_changed() right after that call we will receive error 9x08 NRF_ERROR_INVALID_STATE. In the description of sd_ble_gatts_service_changed() you can find: 

     

    * @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true:
    * - Invalid Connection State
    * - Notifications and/or indications not enabled in the CCCD
    * - An ATT_MTU exchange is ongoing

    My suggestion is to modify the code to delay the MTU exchange after we finish with sending service changed indication. 
    I will report this to R&D to get it fixed in the future. 

  • Hi Hung.

    I am sorry that confirmation is delayed.

    when 「NRF_SDH_BLE_GATT_MAX_MTU_SIZE」 is defined as 247,

    Rather, the Event of「BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST」does not occur.


    (Conversely, when 「NRF_SDH_BLE_GATT_MAX_MTU_SIZE」 is defined as 23, the Event of 「BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST」occurs).

    so that Because of "An ATT_MTU exchange is ongoing", The NRF_ERROR_INVALID_STATE error will not occur.

    It seems to be a different timing problem.

    By the way,

    I would like to test the following proposal separately.

    I would be grateful if you could give me a more specific method.

    「My suggestion is to modify the code to delay the MTU exchange. 」

  • Hi Chan,

    BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST is the event when the central (iphone) request MTU exchange. We are not talking about that, we are talking about the opposite, the nRF5 requests MTU exchange. 

    You can simply test this by comment out sd_ble_gattc_exchange_mtu_request() call inside on_connected_evt() in nrf_ble_gatt.c to test if it works. 

    If it works, then you can think of adding a timing delay before calling that function, so that in case the central didn't do a MTU exchange request, we can request from our side. 

  • Hi Hung.


    I understood what you said. Thank you.

    And I comment out the 「sd_ble_gattc_exchange_mtu_request ()」 from 「on_connected_evt ()」 and tried the test.

    For this reason too, the problem seems to have occurred in 「sd_ble_gatts_service_changed ()」.

    However, I want to take permanent measures against this problem.

    In other words, because of delay is not good in event driven processing based on interrupt, The following measures were taken.

    There was no problem with the test.

    ・#define NRF_BLE_GATT_BLE_OBSERVER_PRIO 1 → #define NRF_BLE_GATT_BLE_OBSERVER_PRIO 2

    But I am curious about the effect on this.

    Please let me know if there are any problems.

  • I'm not sure why changing NRF_BLE_GATT_BLE_OBSERVER_PRIO can solve the problem. 

    By "timing delay" I'm not talking about a loop delay, but about to start a timer and only trigger sd_ble_gattc_exchange_mtu_request () after a period of time. 

    You are saying that by commenting out sd_ble_gattc_exchange_mtu_request () you still have trouble when calling sd_ble_gatts_service_changed() ? Could you check which error code you have ? A sniffer trace would really help as well. 

Related