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

Passing Characteristic data to Function

Hello,

I am having strange issue. I'm getting some data from custom service and characteristic. I can see the data being received is correct. However, if I try to pass the data to some other function in another file, the characteristic stops receiving data. Although the mobile app (nRFConnect) shows data saved, but I can not see data being received on the log. Here is the code snippet:

void scr_on_write(ble_ss_t * p_scr_service, ble_evt_t const * p_ble_evt)
{
    ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    

    if (   (p_evt_write->handle == p_scr_service->char_handles.value_handle))
        //&& (p_evt_write->len == 3)) No limit to the number of bytes.
        //&& (p_rgb_service->rgb_write_handler != NULL))
    {
        //p_led_service->led_write_handler(p_ble_evt->evt.gap_evt.conn_handle, p_led_service, p_evt_write->data[0]);
        NRF_LOG_INFO("Length of script data: %d", p_evt_write->len);
        NRF_LOG_INFO("Script Data starts:");
        NRF_LOG_HEXDUMP_INFO(p_evt_write->data, p_evt_write->len);
        NRF_LOG_INFO("End of script data.");

        // write script data into flash 
        record_update_scr(p_evt_write->data, p_evt_write->len);
   
    }
    else if (   (p_evt_write->handle == p_scr_service->char_handles_1.value_handle)
        && (p_evt_write->len == 1)) 
    {
        NRF_LOG_INFO("Script start/stop: %X", p_evt_write->data[0]);
        set_script_start_flag(p_evt_write->data[0]);
        // save the event and data
        scr_evt_write = p_evt_write;
    }
}

The set_script_start_flag() function simply saves data into a global variable (within that file). If I comment out this function, everything works fine and I can see data in the log. If un-commented, once I send data to this characteristic, all characteristics in all services stop receiving data. 

I have also tried copying p_evt_write globally and later using p_evt_write->data but this also creates problems. What am I missing?

uint8_t global_flag=0;

set_script_start_flag(uint8_t data){
    global_flag = data;
}

Parents
  • I have also tried to implement following code to read characteristic value. 

    void get_script_start_flag(){
        uint8_t testStore;
        ble_gatts_value_t testStruct;
    
        testStruct.p_value = &testStore;
        testStruct.len = 2;
        testStruct.offset = 0;
    
        sd_ble_gatts_value_get(scr_service_instance->conn_handle, scr_service_instance->char_handles_1.value_handle, &testStruct);
        //NRF_LOG_INFO("testStruc: %X,%X", testStruct.p_value[0], testStruct.p_value[1]);
        //return testStruct.p_value[0];
        script_start_flag = testStruct.p_value[0];
    }

    I am reading the value in another function which scan through this value after every second. If I comment out this line:

    script_start_flag = testStruct.p_value[0];

    Everything works fine. As soon as this line is un-commented (values is saved in local variable), and some value is sent from nRFConnect app, all services stop responding, the device comes into a sort of HALT condition. Very frustrating situation.

  • It sounds to me that you're encountering an access conflict.

    Below is a section of code for one of my services.

    lds_drive_data_t is a data structure that I transfer using one of the service characteristics.

    In the bottom of the code you can see that I set a global structure 

    volatile lds_uart_data_t m_lds_RX_data;
    . Note that I have declared it volatile.

    Depending on what is received during the event data is passed to functions pointed to by lds_write_handler or lds_uart_rx_handler

    static void lds_OnWrite(ble_lds_t * p_lds, ble_evt_t const * p_ble_evt)
    {
        VERIFY_PARAM_NOT_NULL_VOID(p_lds);
        VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
    
        /* get the write event data */
        ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        lds_drive_data_t newData = {0};
        /* confirm that characteristic was written to, data length is correct and
        that an event handler has been set */
        if ((p_evt_write->handle == p_lds->lds_char_handles.value_handle) &&
            (sizeof(newData.command) <= p_evt_write->len) && (p_lds->lds_write_handler != NULL))
        {
            memcpy(&newData.command, p_evt_write->data, sizeof(newData.command));
            newData.dataLength = p_evt_write->data[sizeof(newData.command)];
            if (newData.dataLength > 0)
            {
                memcpy(&newData.data,
                       p_evt_write->data + sizeof(newData.command) + sizeof(newData.dataLength),
                       p_evt_write->len - (sizeof(newData.command) + sizeof(newData.dataLength)));
            }
            /* pass write event data to the event handler */
            p_lds->lds_write_handler(p_lds, newData);
        }
        else
        {
            if ((p_evt_write->handle == p_lds->lds_uart_rx_handles.value_handle) &&
            (0 <= p_evt_write->len) && (p_lds->lds_uart_rx_handler != NULL))
            {
                m_lds_RX_data.length = p_evt_write->len;
                m_lds_RX_data.p_data = p_evt_write->data;
            
                /* pass write event data to the event handler */
                p_lds->lds_uart_rx_handler(p_lds, m_lds_RX_data);
            }
        }
    }

    I don't poll for data within the rest of my code at the moment, but if you can't glean anything from my code then you may need to takes steps to prevent access conflicts on the basis that the SoftDevice should take priority over everything else and shouldn't be held up in anyway otherwise it will suffer internal timeouts and the BLE will stop working.

Reply
  • It sounds to me that you're encountering an access conflict.

    Below is a section of code for one of my services.

    lds_drive_data_t is a data structure that I transfer using one of the service characteristics.

    In the bottom of the code you can see that I set a global structure 

    volatile lds_uart_data_t m_lds_RX_data;
    . Note that I have declared it volatile.

    Depending on what is received during the event data is passed to functions pointed to by lds_write_handler or lds_uart_rx_handler

    static void lds_OnWrite(ble_lds_t * p_lds, ble_evt_t const * p_ble_evt)
    {
        VERIFY_PARAM_NOT_NULL_VOID(p_lds);
        VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
    
        /* get the write event data */
        ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        lds_drive_data_t newData = {0};
        /* confirm that characteristic was written to, data length is correct and
        that an event handler has been set */
        if ((p_evt_write->handle == p_lds->lds_char_handles.value_handle) &&
            (sizeof(newData.command) <= p_evt_write->len) && (p_lds->lds_write_handler != NULL))
        {
            memcpy(&newData.command, p_evt_write->data, sizeof(newData.command));
            newData.dataLength = p_evt_write->data[sizeof(newData.command)];
            if (newData.dataLength > 0)
            {
                memcpy(&newData.data,
                       p_evt_write->data + sizeof(newData.command) + sizeof(newData.dataLength),
                       p_evt_write->len - (sizeof(newData.command) + sizeof(newData.dataLength)));
            }
            /* pass write event data to the event handler */
            p_lds->lds_write_handler(p_lds, newData);
        }
        else
        {
            if ((p_evt_write->handle == p_lds->lds_uart_rx_handles.value_handle) &&
            (0 <= p_evt_write->len) && (p_lds->lds_uart_rx_handler != NULL))
            {
                m_lds_RX_data.length = p_evt_write->len;
                m_lds_RX_data.p_data = p_evt_write->data;
            
                /* pass write event data to the event handler */
                p_lds->lds_uart_rx_handler(p_lds, m_lds_RX_data);
            }
        }
    }

    I don't poll for data within the rest of my code at the moment, but if you can't glean anything from my code then you may need to takes steps to prevent access conflicts on the basis that the SoftDevice should take priority over everything else and shouldn't be held up in anyway otherwise it will suffer internal timeouts and the BLE will stop working.

Children
Related