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

BLE_NUS_EVT_RX_DATA triggering twice in my handler

Hello

I have a question i cannot figure out. I'm using my phone to send string on my NUS client (NRF52 with SDK15.3.0 and FreeRTOS) and the event BLE_NUS_EVT_RX_DATA is triggered twice in my handler each time i send only one string ? I'm using serial bluetooth terminal application.

I don't know why this happens. Is it a retry from the sender ? Do i need to ack the sender on the first time ?

If you have any idea about this, feel free to share

Regards,

Aurélien

  • You only need acks from the application level if you're using Indications, notifications, on the other hand does not, and both are ack'ed automatically in the Link Layer. 

    What event handler do you refer to? Maybe you are forwarding the same event to multiple event handlers? 

    Is the data the same in both events, or do they differ? 

    If the characteristic you want to read is longer than the current MTU size the read operation will have to be fragmented and you will probably receive multiple BLE_NUS_EVT_RX_DATA from the NUS service client. 

    See GATTC Characteristic or Descriptor Value Read

  • Hello,

    Thank you very much for the reply. 

     Actually i'm initializing the service like this :

    void services_init(void)
    {
        uint32_t       nus_err_code;
        ble_nus_init_t nus_init;
    
        memset(&nus_init, 0, sizeof(nus_init));
        nus_init.data_handler = nus_server_evt_handler;
    
        nus_err_code = ble_nus_init(&m_nus, &nus_init);
        APP_ERROR_CHECK(nus_err_code);
    }

    In my handler i'm just doing this :

    static void nus_server_evt_handler(ble_nus_evt_t * p_evt)
    {
        NRF_LOG_INFO("nus_server_evt_handler %d",p_evt->type);
        switch (p_evt->type) {
        case BLE_NUS_EVT_RX_DATA :
            NRF_LOG_INFO("BLE_NUS_EVT_RX_DATA");
            break;
        case BLE_NUS_EVT_TX_RDY:
            NRF_LOG_DEBUG("BLE_NUS_EVT_TX_RDY");
            break;
        case BLE_NUS_EVT_COMM_STARTED:
            NRF_LOG_DEBUG("BLE_NUS_EVT_COMM_STARTED");
            break;
        case BLE_NUS_EVT_COMM_STOPPED:
            NRF_LOG_DEBUG("BLE_NUS_EVT_COMM_STOPPED");
            break;
        default:
            break;
        }
    }

    Then i'm sending only one character from my phone, and i can see BLE_NUS_EVT_RX_DATA printed twice...

  • I think i ve made some progress.  Actually, at the begenning i was working without OS but now, i have ported FreeRTOS in my project and regarding the ble_evt_handler here the code i have : 

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        uint16_t role        = ble_conn_state_role(conn_handle);
    
        // Based on the role this device plays in the connection, dispatch to the right handler.
        if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt))
        {
            ble_nus_on_ble_evt(p_ble_evt, &m_nus);
            on_ble_peripheral_evt(p_ble_evt);
        }
        else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))
        {
            ble_nus_c_on_ble_evt(p_ble_evt, &m_ble_nus_c);
            on_ble_central_evt(p_ble_evt);
        }
    }

    I guess i need to comment ble_nus_on_ble_evt and ble_nus_c_on_ble_evt since they ? am i right ?

  • Aurele said:
    I guess i need to comment ble_nus_on_ble_evt and ble_nus_c_on_ble_evt since they ? am i right ?

    What were you trying to say, I think there's a typo.

    I'm not that familiar with FreeRTOS, how do you schedule the execution of event handlers?  

  • oups, sorry, it wasn't clear Slight smile

    I have commented line 9 and line 14 in the previous code like this : 

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        uint16_t role        = ble_conn_state_role(conn_handle);
    
        // Based on the role this device plays in the connection, dispatch to the right handler.
        if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt))
        {
            //ble_nus_on_ble_evt(p_ble_evt, &m_nus);
            on_ble_peripheral_evt(p_ble_evt);
        }
        else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))
        {
            //ble_nus_c_on_ble_evt(p_ble_evt, &m_ble_nus_c);
            on_ble_central_evt(p_ble_evt);
        }
    }

    and now all is working fine. 

    With FreeRTOS, softdevice is scheduled with a specific task and it is started like this : 

    nrf_sdh_freertos_init(NULL, NULL);

    I guess this task is calling my handlers so i think i don't need to schedule them on my own. 

Related