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

ble_app_uart_c losing characters

Hello again Nordic World.

We are slowly attempting to transition from the nRF51 environment to nRF52.  We are starting, not with development environment for our product, (it will remain at the 51 leve for now) but with the replacement of our nRF51 Dongles, which we use with the ble_app_uart_c code as a terminal interface to our board for testing.  We are attempt in to replace the nRF51 Dongle with the nRF52 DK.

The problem is that the ble_app_uart_c code from the 15.2 SDK, running on the 52 DK is dropping characters.   Please review the following snippets and note the alignment and missing characters which always seem to get lost in the 3rd column:

3689 4100 419 3689 4123 0 0 2 4100 4193 0 3689 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5190 4734 1
3682 4100 4193 3682 4123 -7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5191 4735 1
3682 4100 4193 3682 4123 0 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5192 4736 1
3682 4100 4193 3682 4123 0 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5193 4737 1
3682 4100 4193 3682 4123 0 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5194 4738 1
3689 4100 4193 3682 4123 7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5195 4739 1
3682 4100 4193 3682 4123 -7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5196 4740 1
3682 4100 4193 3682 4123 0 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5197 4741 1
3689 4100 4193 3682 4123 7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5198 4742 1
3682 4100 4193 3682 4123 -7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5199 4743 1
3689 4100 419 3682 4123 7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5200 4744 1
3682 4100 4193 3682 4123 -7 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5201 4745 1
3682 4100 4193 3682 4123 0 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5202 4746 1
3682 4100 4193 3682 4123 0 0 2 4100 4193 0 3682 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 5203 4747 1

Here is the exact same information as printed by the 51 Dongle under SDK 12.3:  Note the perfect alignment and no missing characters.

3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4861 4405 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4862 4406 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4863 4407 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4864 4408 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4865 4409 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4866 4410 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4867 4411 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4868 4412 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4869 4413 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4870 4414 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4871 4415 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4872 4416 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4873 4417 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4874 4418 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4875 4419 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4876 4420 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4877 4421 1
3710 4100 4193 3710 4123 0 0 2 4100 4193 0 3710 4123 0 4100 3400 0 4000 3300 0 1 1 0 0 4878 4422 1

Any ideas on where to search for and correct this problem is greatly appreciated.

Robin @ TL

Some additional information requested by stateside FAE:

The dropping is consistent in that the only characters dropped are the 16th, 17th, or possibly 18th (not know as both are spaces) in the first string sent.to each line.  However when it is dropped seems to be somewhat random.

The 52DK is connected form its u-usb connector on board to a USB-C on my computer by a short (~18") cable.

The only change is the hardware and the version of the unaltered example code running on each.

2 each 52DK's and 2 each cables have been tested.

  • Ok. So this is the code that transmits the strings over BLE from the peripheral to the central, right?

    is m_send_chars() the same function as the function send_chars(), which you sent in an earlier snippet in this ticket? Can you either confirm this or send this function? If it is the send_chars() what does your tx_buffer_insert() and tx_buffer_process() look like? It may be other "middle layer" processing functions, so please include functions all the way down to the softdevice calls. What I am looking for in particular is the sd_ble_gatts_hvx() call. How is the return value for this function handled?

  • Hello Edvin,

    Yes, this is the code that gets characters from our app to ble_nus_string_send, via the tx_buffer.

    Yes, m_send_chars() and send_chars() are the same function.

    Here is the chain that I have touched:

    from our app.c:

    ...
            m_send_chars(reply);
    ...

    to main.c:

    ...
    static void send_chars(const char * str)
    {
      if (connected)
      {
        uint8_t i = 0;
        while (str[i] != 0x00) 
        {
          i+=1;
        }
        tx_buffer_insert(&m_nus, (uint8_t*)str, i);
        tx_buffer_process();
      }
    }
    ...

    then on to tx_buffer.c

    #include "ble_nus.h"
    #include "tx_buffer.h"
    #include "string.h"
     
    #define  TX_BUFFER_MASK 31
    
    static tx_message_t m_tx_buffer[32];                                       /**< Transmit buffer for messages to be transmitted to the Notification Provider. */
    static uint32_t     m_tx_insert_index = 0;                                 /**< Current index in the transmit buffer where the next message should be inserted. */
    static uint32_t     m_tx_index        = 0;                                 /**< Current index in the transmit buffer from where the next message to be transmitted resides. */
    
    void tx_buffer_init(void)
    {
      memset(m_tx_buffer, 0, sizeof(m_tx_buffer));
      m_tx_index = 0;
      m_tx_insert_index = 0;
    }
    
    void tx_buffer_insert(ble_nus_t * nus, uint8_t * p_string, uint16_t length)
    {
      memset(&(m_tx_buffer[m_tx_insert_index]), 0, sizeof(tx_message_t));
      memcpy(m_tx_buffer[m_tx_insert_index].p_data, p_string, length);
      m_tx_buffer[m_tx_insert_index].length = length;
      m_tx_buffer[m_tx_insert_index].p_nus = nus;
      m_tx_insert_index++;
      m_tx_insert_index &= TX_BUFFER_MASK;
    }
    
    void tx_buffer_process(void)
    {
      if (m_tx_index != m_tx_insert_index)
      {
        uint32_t err_code;
        err_code = ble_nus_string_send(m_tx_buffer[m_tx_index].p_nus,
                                       m_tx_buffer[m_tx_index].p_data,
                                       m_tx_buffer[m_tx_index].length);
        if (err_code == NRF_SUCCESS)
        {
          ++m_tx_index;
          m_tx_index &= TX_BUFFER_MASK;
        }
      }
    }
    

    Here is untouched code from SDK 12.3 to complete the chain:

    From ble_nus.c:

    uint32_t ble_nus_string_send(ble_nus_t * p_nus, uint8_t * p_string, uint16_t length)
    {
        ble_gatts_hvx_params_t hvx_params;
    
        VERIFY_PARAM_NOT_NULL(p_nus);
    
        if ((p_nus->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_nus->is_notification_enabled))
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        if (length > BLE_NUS_MAX_DATA_LEN)
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_nus->rx_handles.value_handle;
        hvx_params.p_data = p_string;
        hvx_params.p_len  = &length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
    }
    

    From ble_gatts.h

    SVCALL(SD_BLE_GATTS_HVX, uint32_t, sd_ble_gatts_hvx(uint16_t conn_handle, ble_gatts_hvx_params_t const *p_hvx_params));
    

    Thanks,

    Robin @ TL

  • Hello again Edvin,

    Here is another strange behavior I just noted that may help trace this down:

    I have a function to display the contents of flash memory we are using.  When this function is called via the nrf51 dongle everything looks good:

    brdstat: 00000003
    burncnt: 00000014
    bootcnt: 00000000
    tempchk: 00006a40
    temppas: 00000001
    lmpchk : 03039000
    lmppas : 00000001
    ...


    When I call the same function via the nrf52DK, it throws tx power settings logs into the output:

    brdstat: 00000003
    burncnt: 00000014
    bootcnt: 00000000
    tempchk: 00006a40
    TX: -30 dBm
    temppas: 00000001
    TX: -30 dBm
    lmpchk : 03039000
    lmppas : 00000001
    ...

    Might the log messaging be stepping on my uart output?  Perhaps this be a config setting issue?

  • So, an interesting finding on the tx info insertion:

    I have a command that starts with the lone char "t" and is followed by an index into an array.  This is used to set the radio transmit power.  Not that the two strings that precede the "TX: -30 dBm". and are sent from our board via ble, start with the char 't'.  I changed the command to require more chars, and the insertion stopped.  This indicates that, somehow, this char 't' is being picked up from the incoming 52dk stream and returned to our board on the outgoing 52dk stream, no?

    Hope this is more help and less confusion,

    Robin

    Here is the code for the command that "corrected" the behaviour:

    ...
      else if ((strbuf[0] == 't') &                     // v Command to set ble transmit power
               (strbuf[1] == 'x') &
               (strbuf[2] == 'p') &
               (strbuf[3] == 'w') &
               (strbuf[4] == 'r'))
      {                                               // . Likely not needed for production code TBD
        uint32_t errorcode;
        int8_t powers[] = {-30,-20,-16,-12,-8,-4,0,3,4};
        int numpowers = sizeof(powers)/sizeof(int8_t);
        tmp = atoi(&strbuf[5]);
        if (tmp >= numpowers)
        {
          sprintf(reply,"Value < %d\r\n",numpowers);
          m_send_chars(reply);
          return;
        }
        errorcode = sd_ble_gap_tx_power_set(powers[tmp]);
        if (errorcode == NRF_SUCCESS)
        {
          sprintf(reply,"TX: %d dBm\r\n",powers[tmp]);
          m_send_chars(reply);
          return;
        } 
    ...

    Here is the code before "corrective" changes:

    ...
      else if (strbuf[0] == 't')                      // v Command to set ble transmit power
      {                                               // . Likely not needed for production code TBD
        uint32_t errorcode;
        int8_t powers[] = {-30,-20,-16,-12,-8,-4,0,3,4};
        int numpowers = sizeof(powers)/sizeof(int8_t);
        tmp = atoi(&strbuf[1]);
        if (tmp >= numpowers)
        {
          sprintf(reply,"Value < %d\r\n",numpowers);
          m_send_chars(reply);
          return;
        }
        errorcode = sd_ble_gap_tx_power_set(powers[tmp]);
        if (errorcode == NRF_SUCCESS)
        {
          sprintf(reply,"TX: %d dBm\r\n",powers[tmp]);
          m_send_chars(reply);
          return;
        } 
    ...

    Thx

    Robin @ TL

  • I don't understand the way that you use TX_BUFFER_MASK, e.g. in:

    m_tx_index &= TX_BUFFER_MASK.

    And I don't understand where your last snippets are from. But did those corrections solve your issue?

Related