Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ATT_MTU throughput example: data received by responder?

Hello, I'm running the nRF5 SDK's ATT_MTU throughput example and I want to check that the data sent by the 'tester' (nRF52832 in my case) is effectively received by the 'responder' (nRF52840 in my case).

I can check the data sent by the tester but don't see where the data received by the responder can be found in the code.

Anyone that can help me, or tell what I need to do to find it? Thank you very much!

Parents
  • Hi,

    It's a while ago I did this, but I think I found the changes I've made to get it working.

    In amt.h  around line 115 (see comment LVI):

    /**@brief AMT Event structure. */
    typedef struct
    {
        nrf_ble_amtc_evt_type_t evt_type;       //!<  Type of the event. */
        uint16_t                conn_handle;    //!<  Connection handle on which the event  occurred.*/
        uint8_t *               p_rcv_data;     //!<  Pointer to the array of received bytes the length of which is in params.rcv_bytes_cnt (see below). */                                                          */
                                                //!<     LVI: added to the structure because it wasn't in the example implementation.                    */
        union
        {
            nrf_ble_amtc_db_t    peer_db;       //!<  Handles found on the peer device. This will be filled if the evt_type is @ref NRF_BLE_AMT_C_EVT_DISCOVERY_COMPLETE.*/
            nrf_ble_amtc_notif_t hvx;           //!<  Notification data. This will be filled if the evt_type is @ref NRF_BLE_AMT_C_EVT_NOTIFICATION.*/
            uint32_t             rcv_bytes_cnt; //!<  Number of received bytes by the peer. This will be filled if the evt_type is @ref NRF_BLE_AMT_C_EVT_RBC_NOTIFICATION.*/
        } params;
    } nrf_ble_amtc_evt_t;
    

    In amtc.c around line 135 (see comment LVI):

    static void on_hvx(nrf_ble_amtc_t * p_ctx, ble_evt_t const * p_ble_evt)
    {
        // Check if the event if on the link for this instance
        if (p_ctx->conn_handle != p_ble_evt->evt.gattc_evt.conn_handle)
        {
            return;
        }
    
        // Check if this is a AMT notification.
        if (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ctx->peer_db.amt_handle)
        {
            nrf_ble_amtc_evt_t amt_c_evt;
            p_ctx->bytes_rcvd_cnt           += p_ble_evt->evt.gattc_evt.params.hvx.len;
            amt_c_evt.evt_type              = NRF_BLE_AMT_C_EVT_NOTIFICATION;
            amt_c_evt.conn_handle           = p_ble_evt->evt.gattc_evt.conn_handle;
            amt_c_evt.p_rcv_data            = p_ble_evt->evt.gattc_evt.params.hvx.data; // LVI: pointer to pass the received data to event handler
            amt_c_evt.params.hvx.notif_len  = p_ble_evt->evt.gattc_evt.params.hvx.len;
            amt_c_evt.params.hvx.bytes_sent = uint32_decode(p_ble_evt->evt.gattc_evt.params.hvx.data);
            amt_c_evt.params.hvx.bytes_rcvd = p_ctx->bytes_rcvd_cnt;
            p_ctx->evt_handler(p_ctx, &amt_c_evt);
        }
    }

    In main.c in function static void amtc_evt_handler(nrf_ble_amtc_t * p_amt_c, nrf_ble_amtc_evt_t * p_evt) (see comment LVI):

            case NRF_BLE_AMT_C_EVT_NOTIFICATION:
            {
                static uint32_t bytes_cnt  = 0;
                static uint32_t kbytes_cnt = 0;
    
                if (p_evt->params.hvx.bytes_sent == 0)
                {
                    bytes_cnt  = 0;
                    kbytes_cnt = 0;
                }
    
                bytes_cnt += p_evt->params.hvx.notif_len;
    
                // LVI: Get the pointer to the received data the length of which is p_evt->params.hvx.notif_len
                uint8_t * p_received_data = p_evt->p_rcv_data;
    

    That's it as far as I recall. I was setting a breakpoint in main.c to check on the received data.

    I hope this helps.

    Best regards,

    Luc

  • HI, I'm following this thread because I'm managing the same example code to put in communications two nRF52832.

    I would see also which value is attributed to those determinated byte

    void transfer_data() {
        #define AMT_BYTE_TRANSFER_CNT         (244*6000) //so 6000 packets of 244 bytes
        char buffer[AMT_BYTE_TRANSFER_CNT];
          
        for (int i = 0; i < AMT_BYTE_TRANSFER_CNT; i++) {
            buffer[i] = i - (i % 244)*244; 
        }
    }

    Then in amtc_evt_handler I added what you said and also, to see the value of each byte:

    for(uint32_t i = 0; i < 244; i++)
    {
     NRF_LOG_INFO("Byte %d: %d\n", i, p_received_data[i]);
    }

    In this way I obtain somethink like this:

    It seems random values between 0 and 244, why?

    I take this opportunity to ask also why the message "Logs dropped"? It is some problem with the Log buffer (I extent it at the largest dimension)?

  • Hi Stefano

    I would suggest opening a new ticket on this issue, rather than opening an old one. 

    Regarding your code, it seems you are creating a 1440000 byte buffer on the stack. This will certainly fail, since the total RAM in the nRF52832 is 64kB, and the stack is generally much smaller than this (less than 10kB typically). 

    Best regards
    Torbjørn

  • I worked on what you said.

    Now I have a buffer of 244 Bytes and if I have a a DATA_SIZE (data to send) of 244 it will send 1 packet, if I have a DATA_SIZE of 488 it will send 2 packets but if I have some DATA_SIZE > 3*244 it will send just 3 packets. Why?

    Thanks

  • Hi

    Most likely there are no more than 3 buffers available in the Bluetooth stack, and when you try to send more the notify call will block. That said, it should send more packets eventually, once the packets in the buffers are sent over the air and the buffers clear up. 

    From where in the code are you trying to send the data?

    The notify call will block the execution when the buffers are full, and it is a good idea to set up a separate thread that can send data over Bluetooth without impacting the main thread.  

    Best regards
    Torbjørn

Reply
  • Hi

    Most likely there are no more than 3 buffers available in the Bluetooth stack, and when you try to send more the notify call will block. That said, it should send more packets eventually, once the packets in the buffers are sent over the air and the buffers clear up. 

    From where in the code are you trying to send the data?

    The notify call will block the execution when the buffers are full, and it is a good idea to set up a separate thread that can send data over Bluetooth without impacting the main thread.  

    Best regards
    Torbjørn

Children
  • You're right, I didn't thought to clear the buffer. 

    About what you asked me

    From where in the code are you trying to send the data?

    is there:

    #define DATA_SIZE 1024   
    #define PACKET_SIZE (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3)
    
    static void uart_send_data(uint8_t *data, uint16_t length)
    {
        uint32_t err_code;
    
        // Send data with NUS service
        while (length > 0)
        {
            uint16_t packet_length = (length > PACKET_SIZE) ? PACKET_SIZE : length;
            err_code = ble_nus_data_send(&m_nus, data, &packet_length, m_conn_handle);
            if (err_code == NRF_ERROR_INVALID_STATE || err_code == NRF_ERROR_RESOURCES)
            {
                //Waiting for avaible resources
                while (ble_nus_data_send(&m_nus, NULL, &packet_length, m_conn_handle) == NRF_ERROR_RESOURCES)
                {
                    // Process logs to keep the system responsive
                    NRF_LOG_FLUSH();
                }
            }
            else
            {
                APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("Data sent: %d byte", packet_length);
                bsp_board_led_on(BSP_BOARD_LED_2);  
                bsp_board_led_off(BSP_BOARD_LED_2);
                data += packet_length;
                length -= packet_length;
                NRF_LOG_INFO("Data to send: %d byte", length);
            }
        }
    }
    

    And also, I add a case in the bsp_event_handler:

    case BSP_EVENT_KEY_1:
                
                for (uint32_t i = 0; i < DATA_SIZE; i++)
                {
                  data_to_send[i] = (uint8_t)(i % 244);
                }
                
                for(uint32_t i = 0; i < 243; i++)
                {
                   NRF_LOG_INFO("Byte %d: %d\n", i, data_to_send[i]);
                }
                uart_send_data(data_to_send, DATA_SIZE);
                break;

    Thanks

  • Could you advise me a thread about clearing up the buffer please?

  • Hi 

    I forgot you were using the nRF5 SDK, so please ignore my earlier comment regarding threads. 

    A couple of comments to your code: 

    1) I would not recommend calling uart_send_data from the BSP callback directly. You would be much better of either using the app_scheduler library to schedule this activity to be run from the main context, or by simply set a bool flag in the callback that you can later check in the main loop. 

    2) I would recommend implementing a better way to handle the NRF_ERROR_RESOURCES error code (which signals that the SoftDevice buffers are full). Rather than calling the function over and over in a loop you should wait for the BLE_GATTS_EVT_HVN_TX_COMPLETE event to occur, which signals that one or more of the buffers have freed up. 

    I discuss this in more detail here

    Best regards
    Torbjørn

  • Hi,

    Following this thread, I'm trying to understand:

    1) How the data sent is created?

    2) Can I managre data sent? In the sense that I want decide what the board is sending to the other device

    Thanks for the support, 

    Best regards. 

Related