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

Interfacing NiceRF LN610 to nRF52840 via UART

Hello everyone,

I'm trying to interface a NiceRF LN610 LoRaWAN chip to nRF52840 via UART. Initially, I tried communicating with the chip using CP2102 USB-to-TTL module and RealTerm in a Windows 10 PC and manually entering the commands there (after configuring the port properly). The LN610 chip responds and I get the required values to operate the LoRaWAN chip (see attached image, manual commands in green, chip response in yellow)

I then connected the LN610 TX & RX pins to nRF52840 GPIO pins P1.13 & P1.14, respectively, and then used the UART, SERIAL, and LIBUARTE peripheral examples in SDK16 to communicate with the LN610 chip but I failed to get any response from LN610 in each of the examples.

1. uart peripheral example files

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif

#define MAX_TEST_DATA_BYTES     (15U)                /**< max number of test bytes to be used for tx and rx. */
#define UART_TX_BUF_SIZE 256                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 1                         /**< UART RX buffer size. */

void uart_error_handle(app_uart_evt_t * p_event)
{
    switch (p_event->evt_type)
    {
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        case APP_UART_DATA_READY:
            printf("APP_UART_DATA_READY");
            break;

        case APP_UART_TX_EMPTY:
            printf("APP_UART_TX_EMPTY");
            printf("An event indicating that UART has completed transmission of all available data in the TX FIFO.");
            app_uart_flush();
            break;

        case APP_UART_DATA:
            printf("APP_UART_DATA");
            printf("An event indicating that UART data has been received, and data is present in data field. This event is only used when no FIFO is configured.");
            break;

        default:
            break;
    }
}

/* When UART is used for communication with the host do not use flow control.*/
#define UART_HWFC APP_UART_FLOW_CONTROL_DISABLED

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t err_code;

    uint32_t i = 0;

    bsp_board_init(BSP_INIT_LEDS);

    const app_uart_comm_params_t comm_params =
      {
          14, /* UART RX <-> LN610 TX */
          13, /* UART TX <-> LN610 RX */
          UART_PIN_DISCONNECTED,
          UART_PIN_DISCONNECTED,
          UART_HWFC,
          false,
#if defined (UART_PRESENT)
          NRF_UART_BAUDRATE_9600
#else
          NRF_UARTE_BAUDRATE_9600
#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);

/* Test */
    uint8_t tx_data[4] = { 0x24, 0x01, 0x00, 0x25 };
    uint8_t rx_data = 0;
    uint8_t buff[255];

    // Start sending one byte
    for (i = 0; i < 4; i++)
    {
        app_uart_put(tx_data[i]);
    }

    // Receive data
    i = 0;
    while (true)
    {
         app_uart_get(&rx_data);

         buff[i++] = rx_data;
         if (i % 255)
            break;
    }

    return 0;
}
uart_example_sdk_config.h

2. serial peripheral example files

/**
 * Copyright (c) 2016 - 2019, 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.
 *
 * 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,
                      14, /* UART RX <-> LN610 TX */
                      13, /* UART TX <-> LN610 RX */
                      NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED,
                      NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                      NRF_UART_BAUDRATE_9600,
                      UART_DEFAULT_CONFIG_IRQ_PRIORITY);

#define SERIAL_FIFO_TX_SIZE 32
#define SERIAL_FIFO_RX_SIZE 1

NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);


#define SERIAL_BUFF_TX_SIZE 32
#define SERIAL_BUFF_RX_SIZE 1

NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);

NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_DMA,
                      &serial_queues, &serial_buffs, NULL, sleep_handler);


NRF_SERIAL_UART_DEF(serial_uart, 0);

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);

    static uint8_t tx_message[] = { 0x24, 0x01, 0x00, 0x25 };
    uint8_t response = 0;
    uint8_t buff[255] = {0};
    size_t bytes_read;

    ret = nrf_serial_write(&serial_uart, tx_message, 4, NULL, 500);
    APP_ERROR_CHECK(ret);

    (void)nrf_serial_flush(&serial_uart, 0);

/*
    nrf_serial_uninit(&serial_uart);
    nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
    nrf_delay_us(1000);
*/
    uint32_t i = 0;
    while (true)
    {
        uint8_t c;
        nrf_serial_read(&serial_uart, &c, sizeof(c), &bytes_read, 1000);
        if (bytes_read)
        {
            buff[i++] = c;
            if ((i % 255) == 0)
              break;
        }
    }

    return 0;
}

/** @} */
serial_example_sdk_config.h

3. libuarte example files

/**
 * Copyright (c) 2018 - 2019, 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.
 *
 * 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.
 *
 */
/** @file
 * @defgroup libuarte_example_main main.c
 * @{
 * @ingroup libuarte_example
 * @brief Libuarte Example Application main file.
 *
 * This file contains the source code for a sample application using libuarte.
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "nrf_libuarte_async.h"
#include "nrf_drv_clock.h"
#include <bsp.h>
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_queue.h"

NRF_LIBUARTE_ASYNC_DEFINE(libuarte0, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

static volatile bool m_loopback_phase;

typedef struct {
    uint8_t * p_data;
    uint32_t length;
} buffer_t;

NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
    nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
    ret_code_t ret;

    switch (p_evt->type)
    {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            bsp_board_led_invert(0);
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            /*ret = nrf_libuarte_async_tx(p_libuarte,p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            if (ret == NRF_ERROR_BUSY)
            {
                buffer_t buf = {
                    .p_data = p_evt->data.rxtx.p_data,
                    .length = p_evt->data.rxtx.length,
                };

                ret = nrf_queue_push(&m_buf_queue, &buf);
                APP_ERROR_CHECK(ret);
            }
            else
            {
                APP_ERROR_CHECK(ret);
            }*/
            bsp_board_led_invert(1);
            m_loopback_phase = true;
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            if (m_loopback_phase)
            {
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                if (!nrf_queue_is_empty(&m_buf_queue))
                {
                    buffer_t buf;
                    ret = nrf_queue_pop(&m_buf_queue, &buf);
                    APP_ERROR_CHECK(ret);
                    UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));
                }
            }
            bsp_board_led_invert(2);
            break;
        default:
            break;
    }
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    bsp_board_init(BSP_INIT_LEDS);
    
    ret_code_t ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);
  
    nrf_drv_clock_lfclk_request(NULL);

    ret_code_t err_code /*= NRF_LOG_INIT(app_timer_cnt_get);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT()*/;

/* UARTE 0 */
    static uint8_t text[] = { 0x24, 0x01, 0x00, 0x25 };
    static uint8_t text_size = sizeof(text);
    nrf_libuarte_async_config_t nrf_libuarte_async_config0 = {
            .tx_pin     = 13, /* UART TX <-> LN610 RX */
            .rx_pin     = 14, /* UART RX <-> LN610 TX */
            .baudrate   = NRF_UARTE_BAUDRATE_9600,
            .parity     = NRF_UARTE_PARITY_EXCLUDED,
            .hwfc       = NRF_UARTE_HWFC_DISABLED,
            .timeout_us = 100,
            .int_prio   = APP_IRQ_PRIORITY_LOW
    };

    err_code = nrf_libuarte_async_init(&libuarte0, &nrf_libuarte_async_config0, uart_event_handler, (void *)&libuarte0);

    APP_ERROR_CHECK(err_code);

    nrf_libuarte_async_enable(&libuarte0);

    err_code = nrf_libuarte_async_tx(&libuarte0, text, text_size);
    APP_ERROR_CHECK(err_code);

    while (true)
    {
        NRF_LOG_FLUSH();
    }
}


/** @} */
libuarte_example_sdk_config.h

Also tried using UARTE directly from this instruction from https://devzone.nordicsemi.com/f/nordic-q-a/58740/data-throughput-between-nrf52810-ble-uart

https://github.com/andenore/NordicSnippets/blob/master/examples/uart/main.c

#include <nrf.h>

#define PIN_TXD        (13)
#define PIN_RXD        (14)

int main(void)
{
  uint8_t hello_world[] = /*"Hello World!\n"*/ { 0x24, 0x01, 0x00, 0x25 };
  uint8_t hi_there = 0 /*[255] = { 0 }*/;
  
  // Configure the UARTE with no flow control, one parity bit and 115200 baud rate
  NRF_UARTE0->CONFIG = (UART_CONFIG_HWFC_Disabled   << UART_CONFIG_HWFC_Pos) |
                       (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos); 
  
  NRF_UARTE0->BAUDRATE = UARTE_BAUDRATE_BAUDRATE_Baud4800 << UARTE_BAUDRATE_BAUDRATE_Pos;
  
  // Select TX and RX pins
  NRF_UARTE0->PSEL.TXD = PIN_TXD;
  NRF_UARTE0->PSEL.RXD = PIN_RXD;

/*TX*/  
  // Enable the UART (starts using the TX/RX pins)
  NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos;
  
  // Configure transmit buffer and start the transfer
  NRF_UARTE0->TXD.MAXCNT = sizeof(hello_world);
  NRF_UARTE0->TXD.PTR = (uint32_t)&hello_world[0];
  NRF_UARTE0->TASKS_STARTTX = 1;
  
  // Wait until the transfer is complete
  while (NRF_UARTE0->EVENTS_ENDTX == 0)
  {
  }
  
  // Stop the UART TX
  NRF_UARTE0->TASKS_STOPTX = 1;
  // Wait until we receive the stopped event
  while (NRF_UARTE0->EVENTS_TXSTOPPED == 0);
  
  // Disable the UARTE (pins are now available for other use)
  //NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos;


/*RX*/
  // Enable the UART (starts using the TX/RX pins)
  //NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos;
  // Enable the UART RXDRDY interrupt
  NRF_UARTE0->INTENSET = UARTE_INTENSET_RXDRDY_Enabled << UARTE_INTENSET_RXDRDY_Pos;
  // Enable the UART RXTO interrupt
  NRF_UARTE0->INTENSET = UARTE_INTENSET_RXTO_Enabled << UARTE_INTENSET_RXTO_Pos;

  // Configure receive buffer and start receiving
  NRF_UARTE0->RXD.MAXCNT = /*sizeof(hi_there)*/ 1;
  NRF_UARTE0->RXD.PTR = (uint32_t)&hi_there/*[0]*/;
  NRF_UARTE0->TASKS_STARTRX = 1;
  
  // Wait until the receive is started
  while (NRF_UARTE0->EVENTS_RXSTARTED == UARTE_EVENTS_RXSTARTED_EVENTS_RXSTARTED_NotGenerated)
  {
  }

  // Wait until a data is received
  while (    (NRF_UARTE0->EVENTS_RXDRDY == UARTE_EVENTS_RXDRDY_EVENTS_RXDRDY_NotGenerated)
          || (NRF_UARTE0->EVENTS_ENDRX == UARTE_EVENTS_ENDRX_EVENTS_ENDRX_NotGenerated))
  {
      if (NRF_UART0->EVENTS_RXTO == UARTE_EVENTS_RXTO_EVENTS_RXTO_Generated)
          break;
  }
  
  // Stop the UART TX
  NRF_UARTE0->TASKS_STOPRX = 1;
  // Wait until we receive the stopped event
  while (NRF_UARTE0->EVENTS_RXTO == 0);
  
  // Disable the UARTE (pins are now available for other use)
  NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos;



  
  while (1)
  {
    __WFE();
  }
}

Would appreciate if someone could point me on what could possibly be wrong with my UART usage? 

Thank you,

Carlos

Related