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

BT 5.0 on ble_app_uart 2MPHY

Hello All,

I have 2 evaluation boards nrf53840 EVB "PCA10056".

I would like to run on them the "ble_app_uart"  in "nRF5_SDK_15.3.0_59ac345" as following:

  • A custom board send via uart a buffer for example of 30 characters to the peripheral on the pin P0.26 every 5 ms.
  • The Board "peripheral" send this packet via bluetooth to the "central board" (where I uploaded the "ble_app_uart_c" code)
  • The "central board" print via uart the packet received.

Let's say that I have previous tried to remove all the possible bottle necks of the app, for instance commenting out the part where the bytes received from the central board are sent back again:

static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
{
ret_code_t ret_val;

NRF_LOG_DEBUG("Receiving data.");
NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);

for (uint32_t i = 0; i < data_len; i++)
{
do
{
ret_val = app_uart_put(p_data[i]);
if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
{
NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
APP_ERROR_CHECK(ret_val);
}
} while (ret_val == NRF_ERROR_BUSY);
}
if (p_data[data_len-1] == '\r')
{
while (app_uart_put('\n') == NRF_ERROR_BUSY);
}
// if (ECHOBACK_BLE_UART_DATA)
// {
// // Send data back to the peripheral.
// do
// {
// ret_val = ble_nus_c_string_send(&m_ble_nus_c, p_data, data_len);
// if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
// {
// NRF_LOG_ERROR("Failed sending NUS message. Error 0x%x. ", ret_val);
// APP_ERROR_CHECK(ret_val);
// }
// } while (ret_val == NRF_ERROR_BUSY);
// }
}

Then I tried to put this part of code:

ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_2MBPS,
.tx_phys = BLE_GAP_PHY_2MBPS,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);

at the end of the BLE_GAP_EVT_CONNECTED event in the following routine:


static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
on_connect(p_ble_evt);
ret_code_t err_code;
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_2MBPS,
.tx_phys = BLE_GAP_PHY_2MBPS,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
break;

case BLE_GAP_EVT_DISCONNECTED:
on_disconnect(p_ble_evt);
break;

case BLE_GATTS_EVT_WRITE:
on_write(p_ble_evt);
break;

case BLE_GAP_EVT_CONN_PARAM_UPDATE:
on_conn_params_update(p_ble_evt);
break;
}
}

In order to request a phy change (I hope so).

But when I start to send the packet to the board at that speed they disconnect.

Am I doing any mistake? 

Should I change something else in order to get a phy change and using the 2Mbps?

Are there any other bottle necks that I am missing?

Thanks in advance,

Parents
  • Hi Edvin,

    Today I got some new result that now I try to summarize.

    Before, in the instant which I sent the data at that speed from the other side I saw one, max 2 packets and then disconnected and no longer reconnected ( I will try to dig deeper on this).


    Today, however, I made a small change to the code and in particular I call this function

    void phy_update_request(ble_evt_t const * p_ble_evt){
        ret_code_t err_code;
        ble_gap_phys_t const phys =
        {
            .rx_phys = BLE_GAP_PHY_2MBPS,
            .tx_phys = BLE_GAP_PHY_2MBPS,
        };
        err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
        APP_ERROR_CHECK(err_code);
    }

    In the ble_event_handler routine, under the case : BLE_GAP_EVT_CONNECTED in the main.
    After that I did that I can see that it is going way better, in fact now from the "central" side (I'm sending data
    from a micro-controller via UART to the peripheral) I can see the packets arriving good.
    The problem now is that, if for any reason the connection fails the program from the peripheral goes in Fatal Error and
    it remain there, because, even if there is no connection from the "microcontroller" side I am still sending data.
    In fact, if I stop the data streaming, the program exits from the error routine and starts again.
    So at this point I thought how let the micro know when there is a connection
    (via a message on the UART - printf ("BLE Connection OK"), in the connection routine) and when there is no connection.

    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    NRF_LOG_INFO("Connected");

    printf("\r\nBLE CONNECTION ON\r\n");

    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);
    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
    APP_ERROR_CHECK(err_code);

    phy_update_request(p_ble_evt);
    break;

    case BLE_GAP_EVT_DISCONNECTED:

    printf("\r\nBLE CONNECTION OFF\r\n");

    ....
    }


    The problem is that in the BLE_GAP_EVT_DISCONNECTED routine, only the first character of the string is printed and then returns to the error routine.
    at this point I thought of putting a print on the UART in the error routine:

    __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
    __disable_irq();
    NRF_LOG_FINAL_FLUSH();

    #ifndef DEBUG
    printf("DISCONNECTED\n");
    NRF_LOG_ERROR("Fatal error");
    #else
    switch (id)
    .....

    }

    In this case I always have the same problem (it prints only the first character), but prints it several times
    consecutive (enters several times in the error routine). In this way, I thought in setting a character
    (for example -> "*" instead of printf("DISCONNECTED\n")), and once I get, for example, 5 "*" in row I have to stop the streaming from the micro controller side.

    However I don't like this approach so much and I was wondering if there is a way to avoid the problem upstream,
    that is maybe to interrupt the reading on the UART when the connection has not yet happened.

    What do you think about this?

    Anyway thank a lot for your help and your time.

Reply
  • Hi Edvin,

    Today I got some new result that now I try to summarize.

    Before, in the instant which I sent the data at that speed from the other side I saw one, max 2 packets and then disconnected and no longer reconnected ( I will try to dig deeper on this).


    Today, however, I made a small change to the code and in particular I call this function

    void phy_update_request(ble_evt_t const * p_ble_evt){
        ret_code_t err_code;
        ble_gap_phys_t const phys =
        {
            .rx_phys = BLE_GAP_PHY_2MBPS,
            .tx_phys = BLE_GAP_PHY_2MBPS,
        };
        err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
        APP_ERROR_CHECK(err_code);
    }

    In the ble_event_handler routine, under the case : BLE_GAP_EVT_CONNECTED in the main.
    After that I did that I can see that it is going way better, in fact now from the "central" side (I'm sending data
    from a micro-controller via UART to the peripheral) I can see the packets arriving good.
    The problem now is that, if for any reason the connection fails the program from the peripheral goes in Fatal Error and
    it remain there, because, even if there is no connection from the "microcontroller" side I am still sending data.
    In fact, if I stop the data streaming, the program exits from the error routine and starts again.
    So at this point I thought how let the micro know when there is a connection
    (via a message on the UART - printf ("BLE Connection OK"), in the connection routine) and when there is no connection.

    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    NRF_LOG_INFO("Connected");

    printf("\r\nBLE CONNECTION ON\r\n");

    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);
    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
    APP_ERROR_CHECK(err_code);

    phy_update_request(p_ble_evt);
    break;

    case BLE_GAP_EVT_DISCONNECTED:

    printf("\r\nBLE CONNECTION OFF\r\n");

    ....
    }


    The problem is that in the BLE_GAP_EVT_DISCONNECTED routine, only the first character of the string is printed and then returns to the error routine.
    at this point I thought of putting a print on the UART in the error routine:

    __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
    __disable_irq();
    NRF_LOG_FINAL_FLUSH();

    #ifndef DEBUG
    printf("DISCONNECTED\n");
    NRF_LOG_ERROR("Fatal error");
    #else
    switch (id)
    .....

    }

    In this case I always have the same problem (it prints only the first character), but prints it several times
    consecutive (enters several times in the error routine). In this way, I thought in setting a character
    (for example -> "*" instead of printf("DISCONNECTED\n")), and once I get, for example, 5 "*" in row I have to stop the streaming from the micro controller side.

    However I don't like this approach so much and I was wondering if there is a way to avoid the problem upstream,
    that is maybe to interrupt the reading on the UART when the connection has not yet happened.

    What do you think about this?

    Anyway thank a lot for your help and your time.

Children
Related