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

Transmit string through UART error: NRF_ERROR_BUSY

Hello I am fairly new to Nordic. I am able to send and receive a character only but not able to send a string.

I am trying to send a character via RS232 to Tera Term using UART in NRF52832. I have made my own board. I have used UART example from the nordic but, that uses printf to send characters. I have written my own function to send a char/string. It is as follows:

void uart_putstring(const uint8_t * str)
{
    uint32_t err_code;
    uint8_t c;
    uint8_t len = strlen((char *) str);

    for (int i = 0; i < len; i++)
    {
        c = str[i];

        err_code = app_uart_put(c);

        APP_ERROR_CHECK(err_code);

        nrf_delay_us(1250);
    }
}

The function below is use to initialize UART

void Serial_Ext_Init_Lib(void)
{
   uint32_t err_code;

   err_code = app_uart_close();

   APP_ERROR_CHECK(err_code);

   nrf_gpio_cfg_input(UART_RX_Ext_PIN, NRF_GPIO_PIN_PULLUP);
   nrf_gpio_cfg_output(UART_TX_Ext_PIN);

   APP_UART_FIFO_INIT2(&comm_params2,
                                            RX_BUF_SIZE,
                                            TX_BUF_SIZE,
                                            Uart_Evt_Callback2,
                                            UART_IRQ_PRIORITY,
                                            err_code);

   APP_ERROR_CHECK(err_code);
}

The function as stated above, is the callback function.

void Uart_Evt_Callback2(app_uart_evt_t * uart_evt)
{
   uint32_t err_code;
   static char cr;

   switch (uart_evt->evt_type)
   {
      case APP_UART_DATA:
              while(app_uart_get(&cr) != NRF_SUCCESS);
              while(app_uart_put(cr) != NRF_SUCCESS);
              
              // uart_putstring(" Cannot print using this function");

              printf("Char RX/TX : %c \n", cr);
              break;

      case APP_UART_DATA_READY:
              break;

      case APP_UART_TX_EMPTY:
              break;

      default:
              break;
   }
}

So basically, IF the flow is:

MAIN -> Serial_Ext_Init_Lib -> uart_putstring ("I am able to print a string here");

Works like a charm. I can print any number of strings but this is in the main which before the for(;;) or while(1) loop. Basically before the scheduler.

After I enter the scheduler:

Wait for UART interrupt -> Print a char (Works) -> Print another character or another string? (Does not work!)

Error generated using app_uart_put(): NRF_ERROR_BUSY


How can I get rid of this error?

///////////////////////////////////////////////////////

The code was written by someone else before me so I am not sure if the below function is a part of nordic but, I am using it

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 (ret == NRF_ERROR_BUSY)
   {
      return NRF_ERROR_NO_MEM;
   }
   else if (ret != NRF_SUCCESS)
   {
      return NRF_ERROR_INTERNAL;
   }
   else
   {
      return NRF_SUCCESS;
   }
}

Let me know if y'all need more details. Thanks in advance!

Parents
  • Hello,

    FYI you can use the "insert"->"code" to post code that keeps the formatting. Please consider this in the future for better readablilty.

    So what happens when you use uart_putstring() in your interrupt? Do you just not see the UART data, or does the project crash?

    While this is probably very solveable using debugging, I suggest you take a quick look at the ble_app_uart example from our SDK\examples\ble_peripheral\ble_app_uart, and look at how this processes the UART data from the nus_data_handler() event handler.

    Best regards,

    Edvin

Reply
  • Hello,

    FYI you can use the "insert"->"code" to post code that keeps the formatting. Please consider this in the future for better readablilty.

    So what happens when you use uart_putstring() in your interrupt? Do you just not see the UART data, or does the project crash?

    While this is probably very solveable using debugging, I suggest you take a quick look at the ble_app_uart example from our SDK\examples\ble_peripheral\ble_app_uart, and look at how this processes the UART data from the nus_data_handler() event handler.

    Best regards,

    Edvin

Children
  • I have never worked with BLE before. I tried running S132 and S112. Both of them hit NRF_BREAKPOINT_CARD.

  • An answer to your above question: Uartstring() in the handler allows me to send and receive one character. I just cannot print a string using that function. Uartstring() function is nothing but, uart_put_char() in a loop. Prints the first character and does not print the next.

    Handler()
    {
        // Works
        while(app_uart_get(&cr) != NRF_SUCCESS);
        
        // Works
        while(app_uart_put(cr) != NRF_SUCCESS);
        
        // Does not work. Error returned by below function = NRF_ERROR_BUSY
        // app_uart_put() is probably a nordic function
        while(app_uart_put(cr) != NRF_SUCCESS);
    }

  • app_uart_put() is indeed a nordic function. 

     

    _vs said:
    Both of them hit NRF_BREAKPOINT_CARD.

     Try defining "DEBUG" in your preprocessor definitions. If you are not sure how to add preprocessor definitions, please let me know what IDE you are using.

    After adding DEBUG to your preprocessor definitions, try implementing your uart_putstring() like this:

    void uart_putstring(const uint8_t * str)
    {
        uint32_t err_code;
        uint8_t c;
        uint8_t len = strlen((char *) str);
    
        for (int i = 0; i < len; i++)
        {
            c = str[i];
    
            do{
                err_code = app_uart_put(c);
            } while (err_code == NRF_ERROR_BUSY)
    
            APP_ERROR_CHECK(err_code);
        }
    }

    The issue is that the app_uart_put() is called too fast, and you are trying to put new characters while the old ones are still being processed. 

    By keep trying until it no longer returns NRF_ERROR_BUSY() (but still check for other errors) you should be able to put the entire string.

    Best regards,

    Edvin

  • Thanks Edvin, I already tried that and it did not work but, I found another solution. I call the function when my state machine goes to ideal state and it starts working there after!

Related