When using the ble_app_uart example, "Failed receiving NUS message. Error 0x04. " appears

Hi:

My environment is: nRF5_SDK_17.1.0_ddde560,  keil, s113_nrf52_7.2.0_softdevice
When using the ble_app_uart example, "Failed receiving NUS message. Error 0x04. " appears

static void nus_data_handler(ble_nus_evt_t* p_evt)
{

    if (p_evt->type == BLE_NUS_EVT_RX_DATA) {
        uint32_t err_code;

        //        NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART. %d", p_evt->params.rx_data.length);
        //        NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);

        for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++) {
            do {
                err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);

                if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) {
                    NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                    APP_ERROR_CHECK(err_code);
                }
            } while (err_code == NRF_ERROR_BUSY);
        }
    }
}

After investigation, it was found that `NRF_ERROR_NO_MEM` appeared when `app_uart_put`. I tried the following, but still couldn't solve it. Even when the data is far below 115200, this error will occasionally appear.

1. Uarte is turned on, and debugging shows that data is indeed sent and received through uarte.

2. Modify the data sending method in the interrupt.

 case NRF_DRV_UART_EVT_TX_DONE:
	
	//@modify by guojf start
    read_len = 127;
			
	if (app_fifo_read(&m_tx_fifo,tx_buffer,&read_len)== NRF_SUCCESS)
    {
        (void)nrf_drv_uart_tx(&app_uart_inst, tx_buffer, read_len);
    }
    else
    {
        // Last byte from FIFO transmitted, notify the application.
        app_uart_event.evt_type = APP_UART_TX_EMPTY;
        m_event_handler(&app_uart_event);
    }
	//@modify by guojf end
break;

3. Expand txFIFO to #define UART_TX_BUF_SIZE 4096

4. Try to increase the uart priority, but increasing the priority will cause the program to fail to run

I would like to ask the following people, has anyone encountered this problem, or how to solve it, is there something wrong with the method I use?

Thanks!

Parents
  • This is the code I modified and used on my board. I don't have a development board here. If possible, can you help me verify it? My verification logic is as follows

    usr_ble_app_uart_throughput.zip

  • The zip seems to be corrupt/invalid, I am not able to open. I suggest to first verify that the example works as-is before you do any modification. I highly recommend to order yourself a DK for comparison.

    Kenneth

  • Hi Kenneth:

    This example is to test the Bluetooth transmission rate. The problem I am facing now is that the data received by BLE is sent through UART, and the FIFO is full, as mentioned in the title.

    I have tested it without changing any code, and the problem still occurs. I changed the code just to print the BLE receiving rate.

    This zip does have a problem, and I also tried it. You can directly use the code sent by Sigurd Hellesvik for testing.

    Regards

  • Looking at the implementation of app_uart_put() it looks like app_uart_put() changes NRF_ERROR_BUSY to NRF_ERROR_NO_MEM, see here:

    uint32_t app_uart_put(uint8_t byte)
    {
        tx_buffer[0] = byte;
        ret_code_t ret =  nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1);
        if (NRF_ERROR_BUSY == ret)
        {
            return NRF_ERROR_NO_MEM;
        }
        ...
        ...

    So that means in main() you also need to replace NRF_ERROR_BUSY to NRF_ERROR_NO_MEM also. Looks like line 238 and 243 must do this change.

    Kenneth

  • Hi Kenneth

    There is one thing I didn't make clear. I used app_uart_fifo.c.
    First, if I change it as you said above, the uart will lose data. So I used fifo. The code is in nRF5_SDK_17.1.0_ddde560\components\libraries\uart\app_uart_fifo.c +221 in the sdk, and it does return that the fifo is full.

    uint32_t app_uart_put(uint8_t byte)
    {
        uint32_t err_code;
        err_code = app_fifo_put(&m_tx_fifo, byte);
        if (err_code == NRF_SUCCESS)
        {
            // The new byte has been added to FIFO. It will be picked up from there
            // (in 'uart_event_handler') when all preceding bytes are transmitted.
            // But if UART is not transmitting anything at the moment, we must start
            // a new transmission here.
            if (!nrf_drv_uart_tx_in_progress(&app_uart_inst))
            {
                // This operation should be almost always successful, since we've
                // just added a byte to FIFO, but if some bigger delay occurred
                // (some heavy interrupt handler routine has been executed) since
                // that time, FIFO might be empty already.
                if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS)
                {
                    err_code = nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1);
                }
            }
        }
        return err_code;
    }

    Regards

  • During stress testing, it was found that when the Bluetooth signal was poor, the data transmission rate decreased and app_uart_put was more likely to return NRF_ERROR_NO_MEM

  • Remove the serial port sending operation from `nus_data_handler` and use timer to trigger serial port sending to solve the problem.

Reply Children
No Data
Related