Call to app_uart_put() not putting anything on the TX Line

Hello,

I've been trying to get my call to app_uart_put() to actually place bytes on the TX pin. Interestingly enough, my call to app_uart_get() works fine and is able to receive all the commands on the RX pin. I am using SDK v17.0.2. 

My code that initializes the UART is fairly boilerplate:

   if (!uart_instance_activated)
    {
        uart_instance_activated = true;
        uint32_t err_code = NRF_SUCCESS;
        const app_uart_comm_params_t comm_params =
        {
            UART_RX_PIN,
            UART_TX_PIN,
            UART_RTS_PIN_NUMBER,
            UART_CTS_PIN_NUMBER,
            UART_HWFC,
            false,
            NRF_UART_BAUDRATE_115200
        };

        APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                      uart_error_handle,
                APP_IRQ_PRIORITY_LOWEST,
                              err_code);

        APP_ERROR_CHECK(err_code); 
    }

My code that calls app_uart_put()

uint8_t transportSend( const uint16_t bufferSize, uint8_t *pBuffer )
{
    if ( pBuffer == NULL )
    {
        NRF_LOG_INFO("NULL?");
        return TRANSPORT_ERROR;
    }

    uint32_t status = NRF_SUCCESS;

    while (app_uart_put(START_BYTE) != NRF_SUCCESS);
    nrf_delay_ms(10);

    for ( uint16_t i = 0; i < bufferSize; i++ )
    {
        //NRF_LOG_INFO("pBuffer[%d] = %d", i, pBuffer[i]);
        // UART is spaming 0xFF so it has to be escaped
        if ( ( pBuffer[i] == START_BYTE ) ||
             ( pBuffer[i] == STOP_BYTE ) ||
             ( pBuffer[i] == ESCAPE_BYTE ) ||
             ( pBuffer[i] == 0xFF ) )
        {
            //status = app_uart_put( ESCAPE_BYTE );
            while (app_uart_put(ESCAPE_BYTE) != NRF_SUCCESS);
            nrf_delay_ms(10);

            while (app_uart_put(escapeByte( pBuffer[i] )) != NRF_SUCCESS);
            nrf_delay_ms(10);
        }
        else
        {
            while (app_uart_put(pBuffer[i]) != NRF_SUCCESS);
            nrf_delay_ms(10);
        }
    } // end of for-loop

    while (app_uart_put(STOP_BYTE) != NRF_SUCCESS);
    nrf_delay_ms(10);
  
    return TRANSPORT_SUCCESS;
}

and Like I said, my code that calls app_uart_get() works just fine:

static int cala_getChar()
{
    uint8_t input = 0;
    app_uart_get(&input);
    return input;
}

Is app_uart_put() not being called correctly? Doubled checked sdk_config.h and NRFX_UART_ENABLED is 1

  • I had found the problem:

    Before creating an instance of UART, I attempt to gracefully tear down my CLI over UART via:

    nrf_cli_stop(&m_cli_uart); // this succeeds

    and then

    nrf_cli_uninit(&m_cli_uart); // this hangs on NRF_ERROR_BUSY

    due to

        if (cli_flag_processing_is_set(p_cli))
        {
            return NRF_ERROR_BUSY;
        }


    It looks like the SDK never clears the internal flag p_cli. I was able to get around this problem by commenting out flag check.
    Is there a work-around for properly clearing p_cli?

    If I comment cli_flag_processing_is_set() flag check, my UART works great!


  • Does the nrf_cli_uninit() function just hang "forever"? I think implementing a delay or wait function until UART TX/RX transmissions are completed should let the CLI uninit successfully.

    Very glad you got it working as intended though, and I don't see any issues with how you resolved it.

    Best regards,

    Simon

  • Yes, unfortunately, nrf_cli_uninit() will not clear the flag. I've tried looping on the call and nrf_cli_uninit() will always return NRF_ERROR_BUSY. Implementing a delay did not fix the problem. Looks like some other folks on the DevZone have experienced this as well. 

    https://devzone.nordicsemi.com/f/nordic-q-a/80440/cli-stopping-and-uninitializing-error-nrf_error_busy

    I'd prefer to not modify the SDK -- but if necessary, I will.

  • As my colleague Terje suggests. Could it be that you have uninitialized the UART before calling the nrf_cli_uninit() function which causes the CLI to hang and be "busy"?

    Best regards,

    Simon

  • Hi Simon,

    CLI instance was still "busy" from a previous request of it. 

    How did I finally solve this without modifying the SDK? Well here is my code. The key element here is that I have to call the Nordic App Scheduler in order for the internal state flag of the CLI process to "clear" (not be NRF_ERROR_BUSY):

    // Misc Rpc Cmd
    static void cmd_misc_rpc_on(nrf_cli_t const *p_cli, size_t argc, char **argv)
    {
        if (p_cli == NULL)
        {
            NRF_LOG_INFO("Null pointer found in %s() @line %d\n", __FUNCTION__, __LINE__ );
            return;
        }
    
        ASSERT(p_cli);
        ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
    
        // Business end of the command:
        NRF_LOG_INFO("RPC Activated!");
    
        if (!m_rpcActivationFlag)
        {
            // Schedule a graceful teardown of the CLI process and start-up of a
            // generic UART instance. A scheduled task will ensure that the CLI
            // interal state will update itself correctly:
            uint32_t err_code = app_sched_event_put( NULL, 
                                                        0, 
                                  cliGracefulTeardownCb );
            if (err_code != NRF_SUCCESS)
            {
                NRF_LOG_INFO("app_sched_event_put() failed in %s() invokation",
                              __FUNCTION__);
            }
        }
    }
    
    static void cliGracefulTeardownCb( void *pData, const uint16_t size )
    {
        UNUSED_PARAMETER(pData);
        UNUSED_PARAMETER(size);
    
        m_rpcActivationFlag = true;
    
        // Halt the CLI process over UART so that RPC over UART can take
        // control of the TX/RX pins.
        cli_stop();
    
        // Create an instance of UART with the appropriate parameters:
        uint32_t err_code = NRF_SUCCESS;
        const app_uart_comm_params_t comm_params =
        {
                    UART_RX_PIN,
                    UART_TX_PIN,
            UART_RTS_PIN_NUMBER,
            UART_CTS_PIN_NUMBER,
                      UART_HWFC,
                          false,
    #if defined (UART_PRESENT)
        NRF_UART_BAUDRATE_115200
    #else
              NRF_UARTE_BAUDRATE_115200
    #endif
            };
    
        APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                      uart_error_handle,
                APP_IRQ_PRIORITY_LOWEST,
                              err_code);
        {
            APP_ERROR_CHECK(err_code); 
        }
    }
    

    As always, I appreciate the DevZone's help!

Related