Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

In our application we need to receive data from two uart together

Dear Sir,
we are developing an application on the nRF52840 kit with SDK 15.0.0. We are using Keil as compiler. In our application we need to receive data from two uart together. If we use only one uart the application work fine, but if we add the second uart the firmware have a strange behavior: one of the two uart after a certain time stops to work. The time and the uart that stops are not always the same, it seems casual.
What can happen?
Attached you can find the files main.c, the nrf_serial library and the file sdk_config.h.
Please, help us because we are very worry, we need to complete the project soon.


#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#include "nrf.h"
#include "nrf_drv_clock.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_drv_power.h"
#include "nrf_serial.h"
#include "app_timer.h"


#include "app_error.h"
#include "app_util.h"
#include "boards.h"

/** @file
 * @defgroup nrf_serial_example main.c
 * @{
 * @ingroup nrf_serial_example
 * @brief Example of @ref nrf_serial usage. Simple loopback.
 *
 */

#define OP_QUEUES_SIZE          3
#define APP_TIMER_PRESCALER     NRF_SERIAL_APP_TIMER_PRESCALER

static void sleep_handler(void)
{
    __WFE();
    __SEV();
    __WFE();
}

NRF_SERIAL_DRV_UART_CONFIG_DEF ( m_uart0_drv_config,
                      RX_PIN_NUMBER, TX_PIN_NUMBER,
                      RTS_PIN_NUMBER, CTS_PIN_NUMBER,
                      NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                      NRF_UART_BAUDRATE_9600,
											UART_DEFAULT_CONFIG_IRQ_PRIORITY);

NRF_SERIAL_DRV_UART_CONFIG_DEF ( m_serial_uart_badge_reading_drv_config ,
                      3 , 4 ,	// Rx pin = P0.03 -- Tx pin = P0.04
                      RTS_PIN_NUMBER , CTS_PIN_NUMBER ,
                      NRF_UART_HWFC_DISABLED , NRF_UART_PARITY_EXCLUDED ,
                      NRF_UART_BAUDRATE_115200 ,
                      UART_DEFAULT_CONFIG_IRQ_PRIORITY ) ; 

#define SERIAL_FIFO_TX_SIZE 32
#define SERIAL_FIFO_RX_SIZE 32

NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);

NRF_SERIAL_QUEUES_DEF ( serial_uart_badge_reading_queues , SERIAL_FIFO_TX_SIZE , SERIAL_FIFO_RX_SIZE ) ;

#define SERIAL_BUFF_TX_SIZE 1
#define SERIAL_BUFF_RX_SIZE 1

NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);

// Configuro i buffer delle seriali	
NRF_SERIAL_BUFFERS_DEF ( serial_uart_badge_reading_buffs , SERIAL_BUFF_TX_SIZE , SERIAL_BUFF_RX_SIZE ) ;

NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_IRQ,
                      &serial_queues, &serial_buffs, NULL, sleep_handler);
											
											// Configuro le seriali											
NRF_SERIAL_CONFIG_DEF ( serial_uart_badge_reading_config , NRF_SERIAL_MODE_IRQ ,
                        &serial_uart_badge_reading_queues , &serial_uart_badge_reading_buffs , NULL , sleep_handler ) ;	// sostituito NULL ( il secondo ) a sleep_handlerù
												
NRF_SERIAL_UART_DEF ( serial_uart , 0 ) ;

NRF_SERIAL_UART_DEF ( serial_uart_badge_reading , 1 ) ;

char	buff_received_uart_badge [ 30 ] = "" ;
char	tmp_buff_debug  [ 50 ] = "" ;
char	UID_badge [ 10 ] = "" ;

int main(void)
{
    ret_code_t ret ;
		ret_code_t ret_loop ;
	
    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);
    ret = nrf_drv_power_init(NULL);
    APP_ERROR_CHECK(ret);

    nrf_drv_clock_lfclk_request(NULL);
    ret = app_timer_init();
    APP_ERROR_CHECK(ret);

    // Initialize LEDs and buttons.
    bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);

    ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
    APP_ERROR_CHECK(ret);
	
		// Inizializzo la seriale 	
		ret = nrf_serial_init ( &serial_uart_badge_reading , &m_serial_uart_badge_reading_drv_config , &serial_uart_badge_reading_config ) ;
		APP_ERROR_CHECK(ret);
	
    static char tx_message[] = "Hello nrf_serial 1!\n\r";

    ret = nrf_serial_write(&serial_uart,
                           tx_message,
                           strlen(tx_message),
                           NULL,
                           NRF_SERIAL_MAX_TIMEOUT);
													 
    APP_ERROR_CHECK(ret);	

		while (true)
		{
				char a ;
				
				/********************* Seriale 1. *********************
				*/
				ret_loop = nrf_serial_read ( &serial_uart_badge_reading , &a , sizeof ( a ) , NULL , 5 ) ;
			
				if ( ret_loop == NRF_SUCCESS )
				{		
					( void ) nrf_serial_write ( &serial_uart , &a , sizeof ( a ) , NULL , 0 ) ;
					nrf_serial_flush ( &serial_uart_badge_reading , 5 ) ;
					
				}					
						
				char c ;
				
				/********************* Seriale 2. *********************
				*/
				ret = nrf_serial_read ( &serial_uart , &c , sizeof ( c ) , NULL , 5 ) ;        			
				
				if ( ret == NRF_SUCCESS )
				{
					( void ) nrf_serial_write ( &serial_uart , &c , sizeof ( c ) , NULL , 0 ) ;
					nrf_serial_flush ( &serial_uart , 5 ) ;	
					
				}

		}
		
}

/** @} */

/*$$$LICENCE_NORDIC_STANDARD<2016>$$$*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_SERIAL)
#include "nrf_serial.h"

#if defined (UART_PRESENT)

static void event_handler(nrf_serial_t const * p_serial,
                          nrf_serial_event_t event)
{
    if (p_serial->p_ctx->p_config->ev_handler)
    {
        p_serial->p_ctx->p_config->ev_handler(p_serial, event);
    }
}

static void sleep_handler(nrf_serial_t const * p_serial)
{
    if (p_serial->p_ctx->p_config->mode == NRF_SERIAL_MODE_POLLING)
    {
        return;
    }

    if (p_serial->p_ctx->p_config->sleep_handler)
    {
        p_serial->p_ctx->p_config->sleep_handler();
    }
}

static size_t serial_rx(nrf_serial_t const * p_serial,
                        uint8_t * p_buff,
                        size_t length)
{
    if (p_serial->p_ctx->p_config->mode == NRF_SERIAL_MODE_POLLING)
    {
        size_t rx_len = MIN(length, UINT8_MAX);
        size_t len = rx_len;

        while (nrfx_uarte_rx_ready(&p_serial->instance) && len)
        {
            ret_code_t ret = nrfx_uarte_rx(&p_serial->instance, p_buff, 1);
            if (ret != NRF_SUCCESS)
            {
                break;
            }
            p_buff++;
            len--;
        }

        return rx_len - len;
    }

    nrf_queue_t const * p_rxq = p_serial->p_ctx->p_config->p_queues->p_rxq;
    return nrf_queue_out(p_rxq, p_buff, length);
}

static size_t serial_tx(nrf_serial_t const * p_serial,
                        uint8_t const * p_buff,
                        size_t length)
{
    size_t tx_len = 0;

    if (p_serial->p_ctx->p_config->mode == NRF_SERIAL_MODE_POLLING)
    {
        tx_len = MIN(length, UINT8_MAX);
        ret_code_t ret = nrfx_uarte_tx(&p_serial->instance, p_buff, tx_len);
        ASSERT(ret == NRF_SUCCESS)
        return tx_len;
    }

    nrf_queue_t const * p_txq = p_serial->p_ctx->p_config->p_queues->p_txq;
    nrf_serial_buffers_t const * p_buffs = p_serial->p_ctx->p_config->p_buffers;

    /* Try to enqueue data. */
    size_t queue_in_len = nrf_queue_in(p_txq, p_buff, length);
    if (nrfx_uarte_tx_in_progress(&p_serial->instance))
    {
        return queue_in_len;
    }

    size_t len = nrf_queue_out(p_txq, p_buffs->p_txb, p_buffs->tx_size);
    ASSERT(len > 0);
    ret_code_t ret = nrfx_uarte_tx(&p_serial->instance, p_buffs->p_txb, len);
    ASSERT(ret == NRF_SUCCESS);

    return queue_in_len;
}

static void uart_event_handler(nrfx_uarte_event_t const * p_event, void * p_context)
{
    uint32_t ret;
    nrf_serial_t const * p_serial = p_context;

    switch (p_event->type)
    {
        case NRFX_UARTE_EVT_RX_DONE:
        {
            nrf_queue_t const * p_rxq =
                    p_serial->p_ctx->p_config->p_queues->p_rxq;
            size_t len = nrf_queue_in(p_rxq,
                                      p_event->data.rxtx.p_data,
                                      p_event->data.rxtx.bytes);

            if (len < p_event->data.rxtx.bytes)
            {
                event_handler(p_serial, NRF_SERIAL_EVENT_FIFO_ERR);
                break;
            }

            event_handler(p_serial, NRF_SERIAL_EVENT_RX_DATA);
            nrf_serial_buffers_t const * p_buffs =
                    p_serial->p_ctx->p_config->p_buffers;

            ret = nrfx_uarte_rx(&p_serial->instance,
                                  p_buffs->p_rxb,
                                  p_buffs->rx_size);
            ASSERT(ret == NRF_SUCCESS);
            break;
        }
        case NRFX_UARTE_EVT_ERROR:
        {
            event_handler(p_serial, NRF_SERIAL_EVENT_DRV_ERR);
            break;
        }
        case NRFX_UARTE_EVT_TX_DONE:
        {
            nrf_queue_t const * p_txq =
                    p_serial->p_ctx->p_config->p_queues->p_txq;
            nrf_serial_buffers_t const * p_buffs =
                    p_serial->p_ctx->p_config->p_buffers;

            event_handler(p_serial, NRF_SERIAL_EVENT_TX_DONE);
            size_t len = nrf_queue_out(p_txq, p_buffs->p_txb, p_buffs->tx_size);
            if (len == 0)
            {
                break;
            }

            ret = nrfx_uarte_tx(&p_serial->instance, p_buffs->p_txb, len);
            ASSERT(ret == NRF_SUCCESS);
            break;
        }
        default:
            break;
    }
}

ret_code_t nrf_serial_init(nrf_serial_t const * p_serial,
                           nrfx_uarte_config_t const * p_drv_uart_config,
                           nrf_serial_config_t const * p_config)
{
    ret_code_t ret;
    ASSERT(p_serial && p_drv_uart_config && p_config);

    if (p_serial->p_ctx->p_config)
    {
        /*Already initialized.*/
        return NRF_ERROR_MODULE_ALREADY_INITIALIZED;
    }

    if (p_config->mode != NRF_SERIAL_MODE_POLLING)
    {
        ASSERT(p_config->p_queues && p_config->p_buffers);
    }

    nrfx_uarte_config_t drv_config;
    memcpy(&drv_config, p_drv_uart_config, sizeof(nrf_drv_uart_config_t));
    drv_config.p_context = (void *)p_serial;
    #if 0
#if defined(UARTE_PRESENT) && defined(UART_PRESENT)
    drv_config.use_easy_dma = (p_config->mode == NRF_SERIAL_MODE_DMA);
#endif
#endif
    ret = nrfx_uarte_init(&p_serial->instance,
                            &drv_config,
                            p_config->mode == NRF_SERIAL_MODE_POLLING ?
                            NULL : uart_event_handler);
    if (ret != NRF_SUCCESS)
    {
        return ret;
    }

    p_serial->p_ctx->p_config = p_config;

    if (p_serial->p_ctx->p_config->p_queues)
    {
        nrf_queue_reset(p_serial->p_ctx->p_config->p_queues->p_txq);
        nrf_queue_reset(p_serial->p_ctx->p_config->p_queues->p_rxq);
    }

    nrf_mtx_init(&p_serial->p_ctx->read_lock);
    nrf_mtx_init(&p_serial->p_ctx->write_lock);

    p_serial->p_ctx->flags = NRF_SERIAL_RX_ENABLED_FLAG |
                             NRF_SERIAL_TX_ENABLED_FLAG;

    if (drv_config.pseltxd == NRF_UART_PSEL_DISCONNECTED)
    {
        p_serial->p_ctx->flags &= ~NRF_SERIAL_TX_ENABLED_FLAG;
    }

    if (drv_config.pselrxd == NRF_UART_PSEL_DISCONNECTED)
    {
        p_serial->p_ctx->flags &= ~NRF_SERIAL_RX_ENABLED_FLAG;
        return NRF_SUCCESS;
    }

#if 0
    if (p_serial->p_ctx->p_config->mode != NRF_SERIAL_MODE_DMA)
    {
        nrfx_uart_rx_enable(&p_serial->instance);
        if (p_serial->p_ctx->p_config->mode == NRF_SERIAL_MODE_POLLING)
        {
            return NRF_SUCCESS;
        }
    }
#endif
    return nrfx_uarte_rx(&p_serial->instance,
                           p_serial->p_ctx->p_config->p_buffers->p_rxb,
                           p_serial->p_ctx->p_config->p_buffers->rx_size);
}

ret_code_t nrf_serial_uninit(nrf_serial_t const * p_serial)
{
    ASSERT(p_serial);

    if (!p_serial->p_ctx->p_config)
    {
        /*Already uninitialized.*/
        return NRF_ERROR_MODULE_NOT_INITIALIZED;
    }

    if (!nrf_mtx_trylock(&p_serial->p_ctx->write_lock))
    {
        return NRF_ERROR_BUSY;
    }
    if (!nrf_mtx_trylock(&p_serial->p_ctx->read_lock))
    {
        nrf_mtx_unlock(&p_serial->p_ctx->write_lock);
        return NRF_ERROR_BUSY;
    }

    nrfx_uarte_uninit(&p_serial->instance);
    if (p_serial->p_ctx->p_config->p_queues)
    {
        nrf_queue_reset(p_serial->p_ctx->p_config->p_queues->p_txq);
        nrf_queue_reset(p_serial->p_ctx->p_config->p_queues->p_rxq);
    }

    memset(p_serial->p_ctx, 0, sizeof(nrf_serial_ctx_t));
    return NRF_SUCCESS;
}

typedef struct {
    volatile bool expired;
} nrf_serial_timeout_ctx_t;

static void serial_timeout_handler(void * p_context)
{
    nrf_serial_timeout_ctx_t * p_tout_ctx = p_context;
    p_tout_ctx->expired = true;
}


static ret_code_t timeout_setup(nrf_serial_t const * p_serial,
                                app_timer_id_t const * p_timer_id,
                                uint32_t timeout_ms,
                                nrf_serial_timeout_ctx_t * p_tout_ctx)
{
    uint32_t ticks = APP_TIMER_TICKS(timeout_ms);

    if (ticks < APP_TIMER_MIN_TIMEOUT_TICKS)
    {
        p_tout_ctx->expired = true;
        return NRF_SUCCESS;
    }

    ret_code_t ret = app_timer_create(p_timer_id,
                                      APP_TIMER_MODE_SINGLE_SHOT,
                                      serial_timeout_handler);
    if (ret != NRF_SUCCESS)
    {
        return ret;
    }

    return app_timer_start(*p_timer_id, ticks, p_tout_ctx);
}

ret_code_t nrf_serial_write(nrf_serial_t const * p_serial,
                            void const * p_data,
                            size_t size,
                            size_t * p_written,
                            uint32_t timeout_ms)
{
    ret_code_t ret;

    ASSERT(p_serial);
    if (!p_serial->p_ctx->p_config)
    {
        return NRF_ERROR_MODULE_NOT_INITIALIZED;
    }

    if (!(p_serial->p_ctx->flags & NRF_SERIAL_TX_ENABLED_FLAG))
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (size == 0)
    {
        return NRF_SUCCESS;
    }

    if (!nrfx_is_in_ram(p_data) &&
         p_serial->p_ctx->p_config->mode == NRF_SERIAL_MODE_DMA)
    {
        return NRF_ERROR_INVALID_ADDR;
    }

    if (!nrf_mtx_trylock(&p_serial->p_ctx->write_lock))
    {
        return NRF_ERROR_BUSY;
    }

    nrf_serial_timeout_ctx_t tout_ctx = {
            .expired = false,
    };

    if (timeout_ms != NRF_SERIAL_MAX_TIMEOUT)
    {
        ret = timeout_setup(p_serial,
                            p_serial->p_tx_timer,
                            timeout_ms,
                            &tout_ctx);
        if (ret != NRF_SUCCESS)
        {
            nrf_mtx_unlock(&p_serial->p_ctx->write_lock);
            return ret;
        }
    }

    size_t left = size;
    uint8_t const * p_buff = p_data;

    do
    {
        size_t wcnt = serial_tx(p_serial, p_buff, left);
        left -= wcnt;
        p_buff += wcnt;
        if (!left)
        {
            break;
        }

        sleep_handler(p_serial);
    } while (!tout_ctx.expired);

    if (p_written)
    {
        *p_written = size - left;
    }

    if (!tout_ctx.expired && (timeout_ms != NRF_SERIAL_MAX_TIMEOUT))
    {
        (void)app_timer_stop(*p_serial->p_tx_timer);
    }

    nrf_mtx_unlock(&p_serial->p_ctx->write_lock);
    if (left && tout_ctx.expired)
    {
        return NRF_ERROR_TIMEOUT;
    }

    return NRF_SUCCESS;
}

ret_code_t nrf_serial_read(nrf_serial_t const * p_serial,
                           void * p_data,
                           size_t size,
                           size_t * p_read,
                           uint32_t timeout_ms)
{
    ret_code_t ret;

    ASSERT(p_serial);
    if (!p_serial->p_ctx->p_config)
    {
        return NRF_ERROR_MODULE_NOT_INITIALIZED;
    }

    if (!(p_serial->p_ctx->flags & NRF_SERIAL_RX_ENABLED_FLAG))
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (size == 0)
    {
        return NRF_SUCCESS;
    }

    if (!nrf_mtx_trylock(&p_serial->p_ctx->read_lock))
    {
        return NRF_ERROR_BUSY;
    }

    nrf_serial_timeout_ctx_t tout_ctx = {
            .expired = false,
    };

    if (timeout_ms != NRF_SERIAL_MAX_TIMEOUT)
    {
        ret = timeout_setup(p_serial,
                            p_serial->p_rx_timer,
                            timeout_ms,
                            &tout_ctx);

        if (ret != NRF_SUCCESS)
        {
            nrf_mtx_unlock(&p_serial->p_ctx->read_lock);
            return ret;
        }
    }

    size_t left = size;
    uint8_t * p_buff = p_data;
    do
    {
        size_t rcnt = serial_rx(p_serial, p_buff, left);
        left -= rcnt;
        p_buff += rcnt;
        if (!left)
        {
            break;
        }

        if (tout_ctx.expired)
        {
            if (p_serial->p_ctx->p_config->mode != NRF_SERIAL_MODE_POLLING)
            {
                nrfx_uarte_rx_abort(&p_serial->instance);
            }
            break;
        }

        sleep_handler(p_serial);
    } while (1);

    if (p_read)
    {
        *p_read = size - left;
    }

    if (!tout_ctx.expired && (timeout_ms != NRF_SERIAL_MAX_TIMEOUT))
    {
        (void)app_timer_stop(*p_serial->p_rx_timer);
    }

    nrf_mtx_unlock(&p_serial->p_ctx->read_lock);
    if (left && tout_ctx.expired)
    {
        return NRF_ERROR_TIMEOUT;
    }

    return NRF_SUCCESS;
}

ret_code_t nrf_serial_flush(nrf_serial_t const * p_serial, uint32_t timeout_ms)
{

    ret_code_t ret;

    ASSERT(p_serial);
    if (!p_serial->p_ctx->p_config)
    {
        return NRF_ERROR_MODULE_NOT_INITIALIZED;
    }

    if (!(p_serial->p_ctx->flags & NRF_SERIAL_TX_ENABLED_FLAG))
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (p_serial->p_ctx->p_config->mode == NRF_SERIAL_MODE_POLLING)
    {
        return NRF_SUCCESS;
    }

    if (!nrf_mtx_trylock(&p_serial->p_ctx->write_lock))
    {
        return NRF_ERROR_BUSY;
    }

    nrf_serial_timeout_ctx_t tout_ctx = {
            .expired = false,
    };

    if (timeout_ms != NRF_SERIAL_MAX_TIMEOUT)
    {
        ret = timeout_setup(p_serial,
                            p_serial->p_tx_timer,
                            timeout_ms,
                            &tout_ctx);
        if (ret != NRF_SUCCESS)
        {
            nrf_mtx_unlock(&p_serial->p_ctx->write_lock);
            return ret;
        }
    }

    bool empty;
    do
    {
        empty = nrf_queue_is_empty(p_serial->p_ctx->p_config->p_queues->p_txq)
                && !nrfx_uarte_tx_in_progress(&p_serial->instance);
        if (empty)
        {
            break;
        }

        sleep_handler(p_serial);
    } while (!tout_ctx.expired);

    if (!tout_ctx.expired && (timeout_ms != NRF_SERIAL_MAX_TIMEOUT))
    {
        (void)app_timer_stop(*p_serial->p_tx_timer);
    }

    nrf_mtx_unlock(&p_serial->p_ctx->write_lock);
    if (!empty && tout_ctx.expired)
    {
        return NRF_ERROR_TIMEOUT;
    }

    return NRF_SUCCESS;
}

ret_code_t nrf_serial_tx_abort(nrf_serial_t const * p_serial)
{
    ASSERT(p_serial);
    if (!p_serial->p_ctx->p_config)
    {
        return NRF_ERROR_MODULE_NOT_INITIALIZED;
    }

    if (!(p_serial->p_ctx->flags & NRF_SERIAL_TX_ENABLED_FLAG))
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (!nrf_mtx_trylock(&p_serial->p_ctx->write_lock))
    {
        return NRF_ERROR_BUSY;
    }

    nrfx_uarte_tx_abort(&p_serial->instance);
    if (p_serial->p_ctx->p_config->p_queues->p_txq)
    {
        nrf_queue_reset(p_serial->p_ctx->p_config->p_queues->p_txq);
    }

    nrf_mtx_unlock(&p_serial->p_ctx->write_lock);
    return NRF_SUCCESS;
}

ret_code_t nrf_serial_rx_drain(nrf_serial_t const * p_serial)
{
    ASSERT(p_serial);
    if (!p_serial->p_ctx->p_config)
    {
        return NRF_ERROR_MODULE_NOT_INITIALIZED;
    }

    if (!(p_serial->p_ctx->flags & NRF_SERIAL_RX_ENABLED_FLAG))
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (!nrf_mtx_trylock(&p_serial->p_ctx->read_lock))
    {
        return NRF_ERROR_BUSY;
    }

    uint8_t c;
    /*Drain HW FIFO*/
    while (serial_rx(p_serial, &c, sizeof(c)))
    {

    }

    /*Drain SW FIFO*/
    if (p_serial->p_ctx->p_config->p_queues->p_rxq)
    {
        nrf_queue_reset(p_serial->p_ctx->p_config->p_queues->p_rxq);
    }
    nrf_mtx_unlock(&p_serial->p_ctx->read_lock);
    return NRF_SUCCESS;
}
#else
ret_code_t nrf_serial_init(nrf_serial_t const * p_serial,
                           nrf_drv_uart_config_t const * p_drv_uart_config,
                           nrf_serial_config_t const * p_config)
{
    return NRF_ERROR_NOT_SUPPORTED;
}

ret_code_t nrf_serial_uninit(nrf_serial_t const * p_serial)
{
    return NRF_ERROR_NOT_SUPPORTED;
}
ret_code_t nrf_serial_write(nrf_serial_t const * p_serial,
                            void const * p_data,
                            size_t size,
                            size_t * p_written,
                            uint32_t timeout_ms)
{
    return NRF_ERROR_NOT_SUPPORTED;
}
ret_code_t nrf_serial_read(nrf_serial_t const * p_serial,
                           void * p_data,
                           size_t size,
                           size_t * p_read,
                           uint32_t timeout_ms)
{
    return NRF_ERROR_NOT_SUPPORTED;
}
ret_code_t nrf_serial_flush(nrf_serial_t const * p_serial, uint32_t timeout_ms)
{
    return NRF_ERROR_NOT_SUPPORTED;
}
ret_code_t nrf_serial_tx_abort(nrf_serial_t const * p_serial)
{
    return NRF_ERROR_NOT_SUPPORTED;
}
ret_code_t nrf_serial_rx_drain(nrf_serial_t const * p_serial)
{
    return NRF_ERROR_NOT_SUPPORTED;
}

#endif // UART_PRESENT
#endif //NRF_MODULE_ENABLED(NRF_SERIAL)

nrf_serial.hsdk_config.h

  • NRF_LOG may consume one of the UARTs. Try switching to Segger RTT logging.

  • Good morning,

    I saw link you sent me :

    https://devzone.nordicsemi.com/f/nordic-q-a/25173/nrf52840-uart1-not-working-in-sdk-14#post-id-168360

    I followed the indications but the problem it's not solved. I recieve data from both the uart and after a random time interval, one uart stops to receive.
    I think there is a bug in the uart library because the firmare I wrote to test it is very very easy but the problem happen again.
    Attached the test code.
    Please, help us we have a big problem to continue the development of the application.

    /**
     * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     // GM
     
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    #include <stdint.h>
    #include <stdbool.h>
    #include <stddef.h>
    
    #include "nrf.h"
    #include "nrf_drv_clock.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_drv_power.h"
    #include "nrf_serial.h"
    #include "app_timer.h"
    
    
    #include "app_error.h"
    #include "app_util.h"
    #include "boards.h"
    
    /** @file
     * @defgroup nrf_serial_example main.c
     * @{
     * @ingroup nrf_serial_example
     * @brief Example of @ref nrf_serial usage. Simple loopback.
     *
     */
    
    #define OP_QUEUES_SIZE          3
    #define APP_TIMER_PRESCALER     NRF_SERIAL_APP_TIMER_PRESCALER
    
    static void sleep_handler(void)
    {
        __WFE();
        __SEV();
        __WFE();
    }
    
    NRF_SERIAL_DRV_UART_CONFIG_DEF ( m_uart0_drv_config,
                          RX_PIN_NUMBER, TX_PIN_NUMBER,
                          RTS_PIN_NUMBER, CTS_PIN_NUMBER,
                          NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                          NRF_UART_BAUDRATE_9600,
    											UART_DEFAULT_CONFIG_IRQ_PRIORITY ) ;
    
    NRF_SERIAL_DRV_UART_CONFIG_DEF ( m_serial_uart_badge_reading_drv_config ,
                          3 , 4 ,	// Rx pin = P0.03 -- Tx pin = P0.04
                          RTS_PIN_NUMBER , CTS_PIN_NUMBER ,
                          NRF_UART_HWFC_DISABLED , NRF_UART_PARITY_EXCLUDED ,
                          NRF_UART_BAUDRATE_115200 ,
                          UART_DEFAULT_CONFIG_IRQ_PRIORITY ) ; 
    
    #define SERIAL_FIFO_TX_SIZE 64
    #define SERIAL_FIFO_RX_SIZE 128
    
    NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);
    
    NRF_SERIAL_QUEUES_DEF ( serial_uart_badge_reading_queues , SERIAL_FIFO_TX_SIZE , SERIAL_FIFO_RX_SIZE ) ;
    
    #define SERIAL_BUFF_TX_SIZE 1
    #define SERIAL_BUFF_RX_SIZE 1
    
    NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);
    
    // Configuro i buffer delle seriali	
    NRF_SERIAL_BUFFERS_DEF ( serial_uart_badge_reading_buffs , SERIAL_BUFF_TX_SIZE , SERIAL_BUFF_RX_SIZE ) ;
    
    NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_IRQ,
                          &serial_queues, &serial_buffs, NULL, sleep_handler);
    											
    											// Configuro le seriali											
    NRF_SERIAL_CONFIG_DEF ( serial_uart_badge_reading_config , NRF_SERIAL_MODE_IRQ ,
                            &serial_uart_badge_reading_queues , &serial_uart_badge_reading_buffs , NULL , sleep_handler ) ;	// sostituito NULL ( il secondo ) a sleep_handler		
    
    //NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_POLLING,
    //                      NULL, NULL, NULL, NULL);
    //NRF_SERIAL_CONFIG_DEF(serial_uart_badge_reading_config, NRF_SERIAL_MODE_POLLING,
    //                      NULL, NULL, NULL, NULL);
    										
    NRF_SERIAL_UART_DEF ( serial_uart , 0 ) ;
    
    NRF_SERIAL_UART_DEF ( serial_uart_badge_reading , 1 ) ;
    
    char	buff_received_uart_badge [ 30 ] = "" ;
    char	tmp_buff_debug  [ 50 ] = "" ;
    char	UID_badge [ 10 ] = "" ;
    
    int main(void)
    {	
    		ret_code_t ret;
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
        ret = nrf_drv_power_init(NULL);
        APP_ERROR_CHECK(ret);
    
        nrf_drv_clock_lfclk_request(NULL);
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
        // Initialize LEDs and buttons.
        bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);
    
        ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
    		APP_ERROR_CHECK(ret);
    	
    		// Inizializzo la seriale 	
    		ret = nrf_serial_init ( &serial_uart_badge_reading , &m_serial_uart_badge_reading_drv_config , &serial_uart_badge_reading_config ) ;
    		APP_ERROR_CHECK(ret);
    	
        static char tx_message[] = "Hello nrf_serial 2!\n\r";
    
        ret = nrf_serial_write(&serial_uart,
                               tx_message,
                               strlen(tx_message),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
    													 
        APP_ERROR_CHECK(ret);	
    		
    		char	tmp_buff_send [ 10 ] = { 0x50 , 0x00 , 0x05 , 0x23 , 0x04 , 0x64 , 0x03 , 0x01 , 0x00 , 0x14 } ;
    		
    		// Attivo la funzione autolistcard
    		( void ) nrf_serial_write ( &serial_uart_badge_reading , &tmp_buff_send , 10 , NULL , 100 ) ;
    
    		ret_code_t ret_loop ;
    		
    		while (true)
    		{		
    				/********************* Serial 1. *********************
    				*/
    				
    				char c ;
    						
    				ret_loop = nrf_serial_read ( &serial_uart , &c , sizeof ( c ) , NULL , 1 ) ;        			
    				
    				if ( ret_loop != NRF_SUCCESS )
    					;
    				else
    				{
    					( void ) nrf_serial_write ( &serial_uart , "y" , 1 , NULL , 0 ) ;
    					( void ) nrf_serial_flush ( &serial_uart , 0 ) ;					
    					
    				}
    				
    				/********************* Serial 2. *********************
    				*/
    							
    				ret_loop = nrf_serial_read ( &serial_uart_badge_reading , &c , sizeof ( c ) , NULL , 1 ) ;
    			
    				if ( ret_loop != NRF_SUCCESS )
    					;
    				else
    				{								
    					( void ) nrf_serial_write ( &serial_uart , "x" , 1 , NULL , 0 ) ;
    					( void ) nrf_serial_flush ( &serial_uart_badge_reading , 0 ) ;
    					
    				}		
    
    //				nrf_serial_rx_drain ( &serial_uart ) ;
    
    //				nrf_serial_rx_drain ( &serial_uart_badge_reading ) ;				
    								
    		}
    		
    }
    
    /** @} */
    

  • Hi Gianmarco,

    You did replace the files suggested in the thread as well?

    UPDATE for SDK15 users:

    In order to make it work you need to replace:

    • main.c
    • sdk_config
    • nrf_serial.c
    • nrf_serial.h

    Also, do you get any error codes or information when you debug the application?

Related