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

NO MEM error with app_uart_put()

I am trying to make a central device that is similar to the NUS central example in the SDK. I have a function that is the same as ble_nus_chars_received_uart_print to print data over uart. When the app_uart_put() function is called I get error 0x4 which I think is the no memory error(correct me if I'm wrong). Any ideas on how to fix this or what is causing this issue? I can try to post the project files for the central and peripheral devices if that would help.  

static void ble_emg_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);
    }
}

Parents
  • Hello, I had a look at the documentation for app_uart_put

    /**@brief Function for putting a byte on the UART.
     *
     * @details This call is non-blocking.
     *
     * @param[in] byte   Byte to be transmitted on the UART.
     *
     * @retval NRF_SUCCESS        If the byte was successfully put on the TX buffer for transmission.
     * @retval NRF_ERROR_NO_MEM   If no more space is available in the TX buffer.
     *                            NRF_ERROR_NO_MEM may occur if flow control is enabled and CTS signal
     *                            is high for a long period and the buffer fills up.
     * @retval NRF_ERROR_INTERNAL If UART driver reported error.
     */
    uint32_t app_uart_put(uint8_t byte);

    I see that for SDK 14.x, app_uart_put() would propagate the errors from nrf_drv_uart, which could return NRF_ERROR_BUSY. The code would work correctly, but NRF_ERROR_BUSY is not mentioned in the API of the function call.

    perhaps a bug in the SDK 14.x documentation.

    For SDK 15.x however, if the nrf_drv_tx() functions inside app_uart_put() return a NRF_ERROR_BUSY from the underlying code, app_uart_put() turns that into a NRF_ERROR_NO_MEM error before returning to the main application. Thereby correcting the documentation mistake, but also invalidating the code that is looping and waiting for NRF_ERROR_BUSY as a condition instead of NRF_ERROR_NO_MEM.

    So there may be a bug here.

    Have you tried replacing NRF_ERROR_BUSY with NRF_ERROR_NO_MEM in your application?

    The wording of the documentation makes it sound like increasing the tx buffer or disabling flow control can also help.

  • I am using SDK 15.x. It seems that replacing the NRF_ERROR_BUSY with NRF_ERROR_NO_MEM stopped it from stopping the program. I have already disabled control flow and my TX buffer size is 256. Here is what the updated function and uart params.

    #define UART_TX_BUF_SIZE        256                                     /**< UART TX buffer size. */
    #define UART_RX_BUF_SIZE        256 
    
    static void uart_init(void)
    {
        ret_code_t err_code;
    
        app_uart_comm_params_t const comm_params =
        {
            .rx_pin_no    = RX_PIN_NUMBER,
            .tx_pin_no    = TX_PIN_NUMBER,
            .rts_pin_no   = RTS_PIN_NUMBER,
            .cts_pin_no   = CTS_PIN_NUMBER,
            .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
            .use_parity   = false,
            .baud_rate    = UART_BAUDRATE_BAUDRATE_Baud230400
        };
    
        APP_UART_FIFO_INIT(&comm_params,
                           UART_RX_BUF_SIZE,
                           UART_TX_BUF_SIZE,
                           uart_event_handle,
                           APP_IRQ_PRIORITY_LOWEST,
                           err_code);
    
        APP_ERROR_CHECK(err_code);
    }
    
    static void ble_emg_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_NO_MEM))
                {
                    NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                    APP_ERROR_CHECK(ret_val);
                }
            } while (ret_val == NRF_ERROR_NO_MEM);
        }
        if (p_data[data_len-1] == '\r')
        {
            while (app_uart_put('\n') == NRF_ERROR_NO_MEM);
        }
    }

    However, I am still having trouble with reading the data over the serial port. After a short period, the data stops coming and I think what is happening is stalls in the do{}while(ret_val == NRF_ERROR_NO_MEM) loop but I am not completely sure of that.  Any ideas on what the issue may be I have pretty much the same code as from the NUS service.

Reply
  • I am using SDK 15.x. It seems that replacing the NRF_ERROR_BUSY with NRF_ERROR_NO_MEM stopped it from stopping the program. I have already disabled control flow and my TX buffer size is 256. Here is what the updated function and uart params.

    #define UART_TX_BUF_SIZE        256                                     /**< UART TX buffer size. */
    #define UART_RX_BUF_SIZE        256 
    
    static void uart_init(void)
    {
        ret_code_t err_code;
    
        app_uart_comm_params_t const comm_params =
        {
            .rx_pin_no    = RX_PIN_NUMBER,
            .tx_pin_no    = TX_PIN_NUMBER,
            .rts_pin_no   = RTS_PIN_NUMBER,
            .cts_pin_no   = CTS_PIN_NUMBER,
            .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
            .use_parity   = false,
            .baud_rate    = UART_BAUDRATE_BAUDRATE_Baud230400
        };
    
        APP_UART_FIFO_INIT(&comm_params,
                           UART_RX_BUF_SIZE,
                           UART_TX_BUF_SIZE,
                           uart_event_handle,
                           APP_IRQ_PRIORITY_LOWEST,
                           err_code);
    
        APP_ERROR_CHECK(err_code);
    }
    
    static void ble_emg_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_NO_MEM))
                {
                    NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                    APP_ERROR_CHECK(ret_val);
                }
            } while (ret_val == NRF_ERROR_NO_MEM);
        }
        if (p_data[data_len-1] == '\r')
        {
            while (app_uart_put('\n') == NRF_ERROR_NO_MEM);
        }
    }

    However, I am still having trouble with reading the data over the serial port. After a short period, the data stops coming and I think what is happening is stalls in the do{}while(ret_val == NRF_ERROR_NO_MEM) loop but I am not completely sure of that.  Any ideas on what the issue may be I have pretty much the same code as from the NUS service.

Children
No Data
Related