2

I am writing a C++ code and I am struggling with something rather simple:

I have declared an array

uint8_t *received_data as global variable in my code.

Then I allocate its memory inside a function:

void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {

    if(params->type == 3){
        for(int i = 0; i < params->advertisingDataLen; i++){
            if(params->advertisingData[i] == 0x16){
                if(params->advertisingData[i+1] == 0x34 && params->advertisingData[i+2] == 0x23){
                    received_data_size = params->advertisingDataLen - (i + 3);
                    received_data = new uint8_t[received_data_size];
                    for(int index = i+3; index < params->advertisingDataLen; index++){
                        received_data[index] = params->advertisingData[index];
                        //printf("%02x ", received_data[index]);//params->advertisingData[index]);                       
                        //printf("\r\n");
                    }
                }
            }    
        }  
    }
}

Note that the commented printf's are printing the data I receive correctly.

But then in my main when I try the same printf I receive garbage most of the times and some times I receive the last three elements of the array in the first three places and then garbage.

My main is:

int main(void)
{
    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
    ble.init(bleInitComplete);
    bool state = true;
    while(true){
        ble.waitForEvent();
        measurement[2]++;
        printf("In the loop \n");
        for(int i = 0; i < received_data_size; i++){
            printf("%02x ", received_data[i]);//params->advertisingData[index]);                       
            printf("\r\n");
        }
        delete[] received_data;
    }
}

The whole code as of now is:

#include "mbed.h"
#include "ble/BLE.h"

/* Optional: Device Name, add for human read-ability */
const static char     DEVICE_NAME[] = "G4";

uint16_t uuid16_list[]        = {0x2334};

/* You have up to 26 bytes of advertising data to use. */
const static uint8_t AdvData[] = {0x01,0x02,0x03,0x04,0x05};   /* Example of hex data */

uint8_t meas = 0;

uint8_t received_data_size;

static uint8_t *received_data;


uint8_t measurement[] = {0x34,0x23, meas};

/* Optional: Restart advertising when peer disconnects */
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    BLE::Instance().gap().startAdvertising();
}
/**
 * This function is called when the ble initialization process has failed
 */
void onBleInitError(BLE &ble, ble_error_t error)
{
    /* Avoid compiler warnings */
    (void) ble;
    (void) error;

    /* Initialization error handling should go here */
}    


void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {

    if(params->type == 3){
        for(int i = 0; i < params->advertisingDataLen; i++){
            if(params->advertisingData[i] == 0x16){
                if(params->advertisingData[i+1] == 0x34 && params->advertisingData[i+2] == 0x23){
                    received_data_size = params->advertisingDataLen - (i + 3);
                    received_data = new uint8_t[received_data_size];
                    for(int index = i+3; index < params->advertisingDataLen; index++){
                        received_data[index] = params->advertisingData[index];
                        //printf("%02x ", received_data[index]);//params->advertisingData[index]);                       
                        //printf("\r\n");
                    }
                }
            }    
        }  
    }
}

/**
 * Callback triggered when the ble initialization process has finished
 */
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        /* In case of error, forward the error handling to onBleInitError */
        onBleInitError(ble, error);
        return;
    }

    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    /* Set device name characteristic data */
    ble.gap().setDeviceName((const uint8_t *) DEVICE_NAME);

    /* Optional: add callback for disconnection */
    ble.gap().onDisconnection(disconnectionCallback);

    /* Sacrifice 3B of 31B to Advertising Flags */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE );
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);

    /* Sacrifice 2B of 31B to AdvType overhead, rest goes to AdvData array you define */
    //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, AdvData, sizeof(AdvData));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, measurement, sizeof(measurement));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));


    /* Optional: Add name to device */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));

    /* Set advertising interval. Longer interval == longer battery life */
    ble.gap().setAdvertisingInterval(500); /* 100ms */

    /* Start advertising */
    //ble.gap().startAdvertising();

    /*Start Scanning*/
    ble.gap().setScanParams(500 /* scan interval */, 200 /* scan window */);
    ble.gap().startScan(advertisementCallback);
}

int main(void)
{
    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
    ble.init(bleInitComplete);
    bool state = true;
    while(true){
        ble.waitForEvent();
        measurement[2]++;
        printf("In the loop \n");
        for(int i = 0; i < received_data_size; i++){
            printf("%02x ", received_data[i]);//params->advertisingData[index]);                       
            printf("\r\n");
        }
        delete[] received_data;
    }
}

BLE stands for bluetooth low energy. The code is based on examples found at mbed.org

I guess I am missing something, but I am not sure what exactly. Thank you very much for your help.

7
  • 1
    [off topic], avoid global variables. Commented Sep 15, 2017 at 16:21
  • 1
    When do you call your function? Commented Sep 15, 2017 at 16:21
  • 1
    Global variables will end you. You're already skating on thin ice here. This is a whole lot of code with these mystery variables showing up everywhere. The ownership of the allocations seems entirely arbitrary and that will be trouble. Commented Sep 15, 2017 at 16:24
  • 1
    What is your platform? How is your callback registered? What is BLE? Please edit your post with the answers. Commented Sep 15, 2017 at 16:39
  • 2
    As a quality check of your post, please take the code you posted, put into files and compile. Are there any errors? Did you post enough to compile and build? Did you provide input data? Commented Sep 15, 2017 at 16:40

1 Answer 1

3

First of all, without taking a further look at the rest of the code, the first three bytes of your global received_data will never be written. Take a look into this particular part of your advertisementCallback():

for(int index = i+3; index < params->advertisingDataLen; index++){
                    received_data[index] = params->advertisingData[index];

So the index used for writing to received_data always starts at an offset of 3 - never less - , while it should start at 0. Add a dedicated index variable for this purpose. In your main(), you created a loop starting at 0:

for(int i = 0; i < received_data_size; i++){
        printf("%02x ", received_data[i]);

Therefore the first three bytes of your debug output will always contain random data.

Sign up to request clarification or add additional context in comments.

3 Comments

I also stumbled across the line ble.waitForEvent(); . Is your handler advertisementCallback() called asynchronously? Then you should avoid writing the data into a global array, because your data could be overwritten while you process it.
You are correct in all your comments. I fixed the problem by using a vector that is global. It is accessed in the advertisementCallback, in order to pass it the values that I need and then I access it in my main, reading those values and then clear it.
Also the event is asynchronous, but it occurs rather rarely, so if something happens while the code is running it will be added at the bottom of the vector, without influencing the rest of the tasks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.