Unable to find the DFU service while using ble_app_buttonless_dfu example provided in SDK17.

Hi,

I am unable to find the DFU services in example ble_app_buttonless_dfu provided in SDK 17.

Please suggest how to proceed.

Thanks 

Raj

  • Hi Raj,

    The DFU service is included in the ble_app_buttonless_dfu example (you will see many reference to it if you search for "dfu" in main.c), and you will see the device advertising with the DFU UUID if running the example on a DK. Note that it requires bootloader etc, so it requires a bit to et up unless you flash a merged hex file that included everything. Just to see how this shoud work you could flash for instance <SDK>\examples\dfu\secure_dfu_test_images\ble\nrf52832\sd_s132_bootloader_buttonless_with_setting_page_dfu_secure_ble_debug_without_bonds.hex if working with the nRF52 DK.

    If this does not address the issue, then please elaborate/clarify so that I can answer more specifically.

  • Hi Einar,

    Now I am able to put my board(nrf52840) in DFU mode with buttonless code using Esp32 as controller.

    The problem currently i am facing is to send a init packet to my nrf board at data point.

    when ever i am trying to send an init packet, I didn't get any reply at my ESP32 board  and after some time my nrf board comes in application mode from DFU mode.

    For reference i am attaching logs of my ESP32 board

    20:44:24.078 -> Starting Arduino BLE Client application...
    20:44:24.755 -> BLE Advertised Device found: Name: UART_DFU_Test, Address: c3:3e:a6:fb:ed:f4, serviceUUID: 0000fe59-0000-1000-8000-00805f9b34fb
    20:44:24.755 -> Found our device! address: Forming a connection to c3:3e:a6:fb:ed:f4
    20:44:24.789 -> - Created client
    20:44:24.822 -> - Connected to server
    20:44:25.469 -> - Found our Data service
    20:44:25.469 -> - Found our characteristic....
    20:44:25.469 -> - Found our DFU service
    20:44:25.469 -> DFU service canIndicate....
    20:44:25.537 -> Indicate callback
    20:44:25.537 -> 20 01 01(Response from NRF52 to ESP32 corrospondance to 0x01 command )
    20:44:32.153 -> 60 06 01 00 02 00 00 00 00 00 00 00 00 00 00 ((Response from NRF52 to ESP32 corrospondance to 60 01 command for select object))
    20:44:35.154 -> sending create object command...
    20:44:35.188 -> Indicate callback
    20:44:35.188 -> 60 01 01 (Response from NRF52 to ESP32 corrospondance to 0x01, 0x01,0x90,0x00,0x0,0x0 command to create object)
    20:44:35.188 -> Ready to send init Packet
    20:44:35.188 ->

    when i am trying to send init packet as show in log above nothing happens.

    i stored the content of init packet in a local buffer in my code as shown below 

    uint8_t emgPkt3[144] = {0x12,0x8D,0x01,0x0A,0x47,0x08,0x01,0x12,0x43,0x08,0x01,0x10,0x34,0x1A,0x05,0xCA,0x01,0xFE,0x95,0x03,0x20,0x20,0x28,0x20,0x30,0x20,0x38,0xF0,0xA2,0x03,0x42,0x24,0x08,0x03,0x12,0x20,0x65,0x2B,0xCB,0x9A,0xCA,0x79,0xC4,0x5C,0x99,0x81,0x98,0x06,0xF3,0x1E,0x3D,0x27,0xA7,0x08,0x69,0x20,0x20,0x94,0x51,0x7F,0x4B,0xD0,0x14,0x53,0x74,0x55,0x53,0xEF,0x48,0x01,0x52,0x040,0x80,0x01,0x12,0x20,0x10,0x20,0x1A,0x40,0x7B,0x14,0x2F,0xA8,0x3B,0xAA,0xB2,0x4B,0x84,0x5C,0x44,0x59,0xBF,0x05,0x24,0x5A,0xBF,0xDF,0x44,0x24,0x1F,0xC5,0xAE,0x3C,0xF6,0x5C,0x54,0xD0,0x3E,0x84,0xDB,0x04,0xD4,0x8B,0xA6,0x3B,0x64,0xE4,0x30,0x5E,0x8E,0x01,0xEB,0x47,0xDE,0x69,0x79,0x27,0x93,0x09,0xF3,0xE1,0xE2,0xF1,0x1B,0x73,0xE2,0x19,0x6B,0x2F,0xAB,0x1A,0x11,0x0E};

    and sending four bytes at a time till all 144 bytes are completed.

    can you suggest me where i am wrong?

    Thanks 

    Raj

  • Hi Raj,

    It is difficult to say what is happening here. There are a few things you can do to give us a better understanding:

    • Can you flash the nRF with a debug bootloader project (suffixed "_debug")? This has extensive RTT logging and would give a good understanding on how this look from the nRF.
    • Can you share your DFU master code? That is probably where the issue is, and the log you pasted would be much more useful and easy to interpret if I can see the code that produce it.

    Einar

  • Hi Einar,

    RTT Logs : 

    <info> app_timer: RTC: initialized.
    <info> app: Debug logging for UART over RTT started.
    <info> app: Connected
    <info> app: Data len is set to 0xF4(244)
    <info> app: Data len is set to 0xF4(244)
    <info> app: Device is preparing to enter bootloader mode
    
    <info> app: Device will enter bootloader mode
    
    <info> app: Power management wants to reset to DFU mode.
    <info> app: Power management allowed to reset to DFU mode.

    DFU Master /Controller Code of ESP32 : 

    /**
    A BLE client example that is rich in capabilities.
    There is a lot new capabilities implemented.
    author unknown
    updated by chegewara
    */
    //#include "Arduino.h"
    #include "BLEDevice.h"
    //#include "BLEScan.h"
    void setup_MQTT();
    void sendToAzure(uint8_t *pData, size_t length);
    uint8_t startPacket[1] = {0x01};
    bool DfuFlag = 0;
    static BLEUUID serviceUUID1("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"); //Nordic uart service
    static BLEUUID charUUID1Rx("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");  //Nordic Raed characteristics
    static BLEUUID charUUID1Tx("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");  //Nordic write characteristics
    //*******************************************************************************//
    static BLEUUID serviceUUID2("0000fe59-0000-1000-8000-00805f9b34fb"); //DFU service
    static BLEUUID charUUID2Dx("8EC90003-F315-4F60-9FB8-838830DAEA50");  //DFU Buttonless characteristics
    static BLEUUID charUUID2Cx("8EC90001-F315-4F60-9FB8-838830DAEA50");  //DFU controlPoint characteristics
    static BLEUUID charUUID2Px("8EC90002-F315-4F60-9FB8-838830DAEA50");  //DFU dataPacket characteristics
    //8EC90002-F315-4F60-9FB8-838830DAEA50
    //******************************************************************************//
    static boolean doConnect = false;
    static boolean connected = false;
    static boolean doScan = false;
    static BLERemoteCharacteristic *pRemoteCharacteristicRx;
    static BLERemoteCharacteristic *pRemoteCharacteristicTx;
    static BLERemoteCharacteristic *pRemoteCharacteristicDx;
    static BLERemoteCharacteristic *pRemoteCharacteristicCx;
    static BLERemoteCharacteristic *pRemoteCharacteristicPx;
    static BLEAdvertisedDevice *myDevice;
    static BLEAddress *pServerAddress;
    bool flag = 0;
    BLEAdvertisedDevice advertisedDevice1;
    //String myValue;
    size_t arraySize = 0;
    uint8_t *pData1;
    uint8_t emgPkt3[] = {0x12, 0x8D, 0x01, 0x0A, 0x47, 0x08, 0x01, 0x12, 0x43, 0x08, 0x01, 0x10, 0x34, 0x1A, 0x05, 0xCA, 0x01, 0xFE, 0x95, 0x03, 0x20, 0x20, 0x28, 0x20, 0x30, 0x20, 0x38, 0xF0, 0xA2, 0x03, 0x42, 0x24, 0x08, 0x03, 0x12, 0x20, 0x65, 0x2B, 0xCB, 0x9A, 0xCA, 0x79, 0xC4, 0x5C, 0x99, 0x81, 0x98, 0x06, 0xF3, 0x1E, 0x3D, 0x27, 0xA7, 0x08, 0x69, 0x20, 0x20, 0x94, 0x51, 0x7F, 0x4B, 0xD0, 0x14, 0x53, 0x74, 0x55, 0x53, 0xEF, 0x48, 0x01, 0x52, 0x040, 0x80, 0x01, 0x12, 0x20, 0x10, 0x20, 0x1A, 0x40, 0x7B, 0x14, 0x2F, 0xA8, 0x3B, 0xAA, 0xB2, 0x4B, 0x84, 0x5C, 0x44, 0x59, 0xBF, 0x05, 0x24, 0x5A, 0xBF, 0xDF, 0x44, 0x24, 0x1F, 0xC5, 0xAE, 0x3C, 0xF6, 0x5C, 0x54, 0xD0, 0x3E, 0x84, 0xDB, 0x04, 0xD4, 0x8B, 0xA6, 0x3B, 0x64, 0xE4, 0x30, 0x5E, 0x8E, 0x01, 0xEB, 0x47, 0xDE, 0x69, 0x79, 0x27, 0x93, 0x09, 0xF3, 0xE1, 0xE2, 0xF1, 0x1B, 0x73, 0xE2, 0x19, 0x6B, 0x2F, 0xAB, 0x1A, 0x11, 0x0E};
    uint8_t count = 0;
    static void indicateCallback(
    
        BLERemoteCharacteristic *pBLERemoteCharacteristic,
        uint8_t *pData,
        size_t length,
        bool isNotify)
    {
        arraySize = length;
        pData1 = pData;
        Serial.print("Indicate callback\n");
        for (uint8_t i = 0; i < length; ++i)
        {
            Serial.print(pData[i], HEX);
            Serial.print("\n");
        }
        if (pData[0] == 0x60 && pData[1] == 0x01 && pData[2] == 0x01)
        {
            flag = 1;
        }
        Serial.print("\n");
    }
    
    static void notifyCallback(
        BLERemoteCharacteristic *pBLERemoteCharacteristic,
        uint8_t *pData,
        size_t length,
        bool isNotify)
    {
        Serial.print("Notify data: ");
        for (uint8_t i = 0; i < length; ++i)
        {
            Serial.print(pData[i], HEX);
            Serial.print("\n");
        }
        Serial.print("\n");
        //sendToAzure(pData, length);
    }
    
    static void packetCallback(
        BLERemoteCharacteristic *pBLERemoteCharacteristic,
        uint8_t *pData,
        size_t length,
        bool isNotify)
    {
        Serial.print("Packet data: ");
        for (uint8_t i = 0; i < length; ++i)
        {
            Serial.print(pData[i], HEX);
            Serial.print("\n");
        }
        Serial.print("\n");
        //sendToAzure(pData, length);
    }
    
    class MyClientCallback : public BLEClientCallbacks
    {
        void onConnect(BLEClient *pclient)
        {
        }
    
        void onDisconnect(BLEClient *pclient)
        {
            connected = false;
            Serial.println("onDisconnect");
        }
    };
    
    void checkCharacteristics(BLERemoteCharacteristic *pRemoteCharacteristic)
    {
        Serial.print(" -- canRead?: ");
        Serial.println(pRemoteCharacteristic->canRead() ? "YES" : "NO");
        Serial.print(" -- canNotify?: ");
        Serial.println(pRemoteCharacteristic->canNotify() ? "YES" : "NO");
        Serial.print(" -- canWrite?: ");
        Serial.println(pRemoteCharacteristic->canWrite() ? "YES" : "NO");
        Serial.print(" -- canIndicate?: ");
        Serial.println(pRemoteCharacteristic->canIndicate() ? "YES" : "NO");
    }
    
    bool connectToServer()
    {
        Serial.print("Forming a connection to ");
        Serial.println(myDevice->getAddress().toString().c_str());
    
        BLEClient *pClient = BLEDevice::createClient();
        Serial.println(" - Created client");
    
        pClient->setClientCallbacks(new MyClientCallback());
    
        // Connect to the remove BLE Server.
        pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
        Serial.println(" - Connected to server");
    
        // Obtain a reference to the service we are after in the remote BLE server.
        BLERemoteService *pRemoteService;
        if (DfuFlag == 0)
        {
            pRemoteService = pClient->getService(serviceUUID1);
            if (pRemoteService == nullptr)
            {
                Serial.print("Failed to find our service UUID: ");
                Serial.println(serviceUUID2.toString().c_str());
                pClient->disconnect();
                return false;
            }
            else
            {
                Serial.println(" - Found our Data service");
            }
            // Obtain a reference to the characteristic in the service of the remote BLE server.
            pRemoteCharacteristicRx = pRemoteService->getCharacteristic(charUUID1Rx);
            pRemoteCharacteristicTx = pRemoteService->getCharacteristic(charUUID1Tx);
            if (pRemoteCharacteristicRx == nullptr /* || pRemoteCharacteristicTx == nullptr)*/)
            {
                Serial.print("Failed to find our characteristic UUID: ");
                pClient->disconnect();
                return false;
            }
            Serial.println(" - Found our characteristic....");
            pRemoteService = pClient->getService(serviceUUID2);
            if (pRemoteService == nullptr)
            {
                Serial.print("Failed to find our service UUID: ");
                Serial.println(serviceUUID2.toString().c_str());
                pClient->disconnect();
                return false;
            }
            else
            {
                Serial.println(" - Found our DFU service");
            }
            pRemoteCharacteristicDx = pRemoteService->getCharacteristic(charUUID2Dx);
            if (pRemoteCharacteristicDx->canIndicate())
            {
                Serial.println("DFU service canIndicate....");
                pRemoteCharacteristicDx->registerForNotify(indicateCallback, 0);
                uint8_t emgPkt[1] = {0x01};
                pRemoteCharacteristicDx->writeValue(emgPkt, 1, true);
                DfuFlag = 1;
            }
            if (pRemoteCharacteristicDx->canNotify())
            {
                Serial.println("DFU service canNotify ....");
                pRemoteCharacteristicDx->registerForNotify(notifyCallback);
            }
            connected = true;
            return true;
        }
        else
        {
            //Serial.println(" - Found our characteristic ");
            pRemoteService = pClient->getService(serviceUUID2);
            if (pRemoteService == nullptr)
            {
                Serial.print("Failed to find our servicein DFU mode UUID: ");
                Serial.println(serviceUUID2.toString().c_str());
                pClient->disconnect();
                return false;
            }
            else
            {
                Serial.print("\nFound DFU service");
                Serial.print(pRemoteService->toString().c_str());
            }
            pRemoteCharacteristicCx = pRemoteService->getCharacteristic(charUUID2Cx);
            pRemoteCharacteristicPx = pRemoteService->getCharacteristic(charUUID2Px);
            Serial.print("\n\n\n");
            Serial.print(pRemoteCharacteristicPx->toString().c_str());
            if (pRemoteCharacteristicPx == nullptr || pRemoteCharacteristicCx == nullptr)
            {
                Serial.print("\nFailed to find our characteristic UUID: ");
                pClient->disconnect();
                return false;
            }
            else
            {
                Serial.print("\nFound DFU Data Characteristics");
                if (pRemoteCharacteristicPx->canNotify())
                {
                    Serial.print("\nPacket characreistics can notify");
                    pRemoteCharacteristicPx->registerForNotify(packetCallback, 1);
                }
                if (pRemoteCharacteristicPx->canIndicate())
                {
                    Serial.print("\nPacket characreistics can Indicate");
                    pRemoteCharacteristicPx->registerForNotify(packetCallback, 0);
                }
            }
            Serial.println("\nCharacteristicPx:, CharacteristicCx: ");
            if (pRemoteCharacteristicCx->canNotify())
            {
                Serial.println("DFU service1 can Notify....");
                pRemoteCharacteristicCx->registerForNotify(indicateCallback, 1);
                delay(100);
                uint8_t emgPkt1[2] = {0x06, 0x01};
                pRemoteCharacteristicCx->writeValue(emgPkt1, 2, true);
                delay(3000);
                uint8_t emgPkt2[6] = {0x01, 0x01, 0x90, 0x00, 0x00, 0x00};
                Serial.println("sending create object command...");
                pRemoteCharacteristicCx->writeValue(emgPkt2, 6, true);
                //delay(2000);
                while (!flag)
                    ;
                flag = 0;
                Serial.print("Ready to send init Packet\n");
                if (pRemoteCharacteristicPx != nullptr)
                {
                    for (int i = 0; i < 14; i++)
                    {
                        Serial.printf("Init i = %d", i);
                        pRemoteCharacteristicPx->writeValue(emgPkt3 + count, 10, true);
                        count += 10;
                    }
                    pRemoteCharacteristicPx->writeValue(emgPkt3 + count, 4, true);
                }
                else
                {
                    Serial.print("pRemoteCharacteristicPx is null");
                }
                uint8_t emgPkt4[1] = {0x03};
                pRemoteCharacteristicCx->writeValue(emgPkt4, 1, true);
                delay(1000);
                uint8_t emgPkt5[1] = {0x04};
                pRemoteCharacteristicCx->writeValue(emgPkt5, 1, true);
            }
            connected = true;
            return true;
        }
    }
    
    /**
    Scan for BLE servers and find the first one that advertises the service we are looking for.
    */
    
    class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
    {
    /**
    Called for each advertising BLE server.
    */
        void onResult(BLEAdvertisedDevice advertisedDevice)
        {
            Serial.print("BLE Advertised Device found: ");
            Serial.println(advertisedDevice.toString().c_str());
            advertisedDevice1 = advertisedDevice;
            // We have found a device, let us now see if it contains the service we are looking for.
            if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID2))
            {
    
                //
                Serial.print("Found our device! address: ");
                BLEDevice::getScan()->stop();
    
                myDevice = new BLEAdvertisedDevice(advertisedDevice);
                doConnect = true;
                doScan = true;
    
            } // Found our server
        }     // onResult
    };        // MyAdvertisedDeviceCallbacks
    
    void setup(void)
    {
        Serial.begin(115200);
        Serial.println("Starting Arduino BLE Client application...");
        //setup_MQTT();
        //fileDownload();
        BLEDevice::init("");
        // Retrieve a Scanner and set the callback we want to use to be informed when we
        // have detected a new device. Specify that we want active scanning and start the
        // scan to run for 5 seconds.
        BLEScan *pBLEScan = BLEDevice::getScan();
        pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
        pBLEScan->setInterval(1349);
        pBLEScan->setWindow(449);
        pBLEScan->setActiveScan(true);
        pBLEScan->start(5, false);
    } // End of setup.
    
    // This is the Arduino main loop function.
    void loop(void)
    {
        //Serial.println("We are now ready to download file");
    
        // If the flag "doConnect" is true then we have scanned for and found the desired
        // BLE Server with which we wish to connect. Now we connect to it. Once we are
        // connected we set the connected flag to be true.
        if (doConnect == true)
        {
            if (connectToServer())
            {
                Serial.println("We are now connected to the BLE Server.");
                /*if (advertisedDevice1.haveServiceUUID() && advertisedDevice1.getServiceUUID().equals(serviceUUID2)) {
                Serial.println("DFU service find...");
                }
                else{
                Serial.println("Unable to find DFU service...");
                }*/
            }
            else
            {
                Serial.println("We have failed to connect to the server; there is nothin more we will do.");
            }
            doConnect = false;
        }
    
        // If we are connected to a peer BLE Server, update the characteristic each time we are reached
        // with the current time since boot.
        if (connected)
        {
    
            //Serial.println("Sending DFU enter command");
            //pRemoteCharacteristicRx->writeValue(0x01);
            delay(1000);
        }
        else if (doScan)
        {
            BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
        }
        delay(10); // Delay a second between loops.
    } // End of loop
    

    Code gets stuck here : for(int i = 0; i < 7;i++){
    pRemoteCharacteristicPx->writeValue(emgPkt3+count, 20, true);
    count += 20;
    }

    where pRemoteCharacteristicPx is DFU Packet .

    here in first call to  writeValue() api, code gets stuck and never reaches i = 1.

    ty,

    Raj  

  • Hi Raj,

    I see that the RTT log is from the application and not the bootloader. Can you upload the RTT log from the bootloader instead? (In some cases using the RTT viewer can be difficult when RTT logging is enabled in both the bootloader and application, but a simple workaround is to disable RTT logging in the application when you test).

    PS: I took the liberty to improve the readability of your code. Please use Insert -> Code in the future when inserting code, as that makes it a lot easier to read it.

    Einar

Related