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

Zigbee and Serial communication issue

Hello Nordic!

I have been developing a Zigbee application and now, I need to connect via Serial communication with another device. I just need to listen to the port, not send any data. Unfortunately I don't have that device so I am simulating it with an Arduino Uno. It is configured as the original device at 19200baud, 8bit, 1 stop bit. First of al, is there any other better way to read data through RX/TX? Any other libraries instead of libuarte?

I found the libuarte example which I modified and make it work for my needs. It reads my Arduino via Serial communication correctly and I obtain the characters nicely. My problem occurs when I try to implement the libuarte code into mine. I have had several problems with the sdk_config file. But once the errors have faded out and the code have compiled, I have flashed it into the nrf52840DK board but the Zigbee and Serial communication suddenly stopped working. Could it be that they share some timer or some other peripheral?

I have tried changing the timer for the serial communication but achieved nothing. What may be causing this issue?

The modified code of the libuarte's example is as follows:

/**
 * Copyright (c) 2018 - 2020, 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(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

static uint8_t text[] = "UART example started.\r\n Loopback:\r\n";
static uint8_t text_size = sizeof(text);
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();

    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
            .tx_pin     = TX_PIN_NUMBER,
            .rx_pin     = RX_PIN_NUMBER,
            .baudrate   = NRF_UARTE_BAUDRATE_19200,
            .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(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);

    APP_ERROR_CHECK(err_code);

    nrf_libuarte_async_enable(&libuarte);

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

    while (true)
    {
        NRF_LOG_FLUSH();
    }
}


/** @} */

Thanks to all in advance!

Cheers!

Parents
  • Hello,

    Perhaps you can look into the Zigbee CLI example found in:

    SDK_for_thread_and_zigbee_v4.1.0\examples\zigbee\experimental\cli\cli_agent_router, which is an example where a lot of the zigbee api is serialized.

    If you want to continue on the libuarte path, did you try writing something to the log? Try adding:

    NRF_LOG_INFO("starting application"); right after NRF_LOG_DEFAULT_BACKENDS_INIT(). Do you see the log anywhere? (RTT perhaps, if you are using UART for your application).

    If you see the log, does the log say anything when your application isn't working?

    BR,
    Edvin

  • Hello Edvin!

    Thanks for your quick reply!

    Could you specify a bit more what should I look at in the cli_agent_router example? The code is too short...

    About the log, I haven't had time to learn how to use the NRF_LOG so what I am using is the printf function to show some info via Debug Terminal (in Segger). May you link some information about how to use it? I guess it is more useful than the printf function that I am currently using.

    Anyway, I placed the printf function right under the NRF_LOG_DEFAULT_BACKENDS_INIT() call and it didn't show in the debug terminal... What could be causing this  issue?

    What I found is that the call to nrf_drv_clock_init() is failing, it is returning 0x85 error code. I will debug a bit more this...

    EDIT: I just found out that the error code 0x0085 means that the module is already initialized. So I think I can either remove that call or remove the call to the APP_ERROR_CHECK function. Am I right? Unfortunately the code still fails in the call to NRF_LOG_DEFAULT_BACKENDS_INIT()... I will continue to investigate this issue...

    Thanks in advance!

  • Hello Edvin!

    I finally made it, I have the Serial communication working but I still have some doubts...

    - I receive data via Serial correctly but sometimes I get some communication errors. The most frequent is the error code 1. What does it mean? Where can I find a table/list of the error codes and the associated explanation?

    - When I set the Serial communication, the BLE stops working. I remember seeing something about RTT in my sdk_config file, is this related?. What may be causing this issue? Right now it's not a big problem but I will need to implement BLE in the future so I need to fix this.

    - I also had to delete the APP_ERROR_HANDLER call in the APP_UART_COMMUNICATION_ERROR case in uart_event_handle() function when an error occurs because it was stopping my code. I will have to handle the errror codes manually. For me, there is no problem, but for the board? Is it better to use the error_handler or the error_check than to do it manually?

    Thanks for all your help. As you said, the ble_app_uart gave me the inspiration I needed. OOnce I've cleared my doubts, I will verify the answer and finish this thread.

    Thanks again!

    Cheers!

  • Hi Alejandro,

    Edvin is on leave so I am taking over this thread and will try to assist you. I am not an expert in Zigbee, but I have good understanding on the UART related issues which hopefully will be useful in this case.

    mazis said:
    - I receive data via Serial correctly but sometimes I get some communication errors. The most frequent is the error code 1. What does it mean? Where can I find a table/list of the error codes and the associated explanation?

    I think what you are seeing is somewhat similar to this error. There was a bug where the communication which does not translate the internal hardware error src to library specific error. Probably you should figure out what this error was and how to handle this specific error in your case. 

     

    mazis said:
    - I also had to delete the APP_ERROR_HANDLER call in the APP_UART_COMMUNICATION_ERROR case in uart_event_handle() function when an error occurs because it was stopping my code. I will have to handle the errror codes manually. For me, there is no problem, but for the board? Is it better to use the error_handler or the error_check than to do it manually?

    It is good idea that you handle this errors manually but I recommend you to do it inside the error_handler to make it architecturally same as before.

     

    mazis said:
    Thanks for all your help. As you said, the ble_app_uart gave me the inspiration I needed. OOnce I've cleared my doubts, I will verify the answer and finish this thread.

     Thanks for the kind words and again sorry for the late reply.

  • Hello Susheel!

    From what I read, the problem is that I am not reading the registers fast enough, right? I am not using the FIFO rergister, I don't know if that is relevant. Anyway, I will try to fix it as soon as possible. What do you think is the best approach to solve the issue?

    It is good idea that you handle this errors manually but I recommend you to do it inside the error_handler to make it architecturally same as before.

    What do you mean? Modify the SDK API error_handler function? Would you mind elaborate on this a bit more? I find it pretty interesting to me.

    Furthermore, did you see the last comment I posted? The one below me about the issue with Zigbee and BLE.

    Cheers!

  • mazis said:
    From what I read, the problem is that I am not reading the registers fast enough, right? I am not using the FIFO rergister, I don't know if that is relevant. Anyway, I will try to fix it as soon as possible. What do you think is the best approach to solve the issue?

     Use flow control if possible (change NRF_UARTE_HWFC_DISABLED to NRF_UARTE_HWFC_ENABLED)

    Also try with application uart priority APP_IRQ_PRIORITY_HIGH instead of APP_IRQ_PRIORITY_LOW.

    I think that you are doing a lot of uart post processing, which is causing the hardware FIFO to overflow causing overrun errors. Enabling hardware flow control will greatly reduce the chance of this overrun error. 

     

    mazis said:
    What do you mean? Modify the SDK API error_handler function? Would you mind elaborate on this a bit more? I find it pretty interesting to me.

     No need to change any SDK API, what I mean to say is that when you get any errors and your application is notified using NRF_DRV_UART_EVT_ERROR, then you need to handle it properly. Sometimes you might have to read an extra char from the FIFO to restart the state machine of the underlying driver. Please look at other examples in the SDK that handle this NRF_DRV_UART_EVT_ERROR event.

     

    mazis said:
    Furthermore, did you see the last comment I posted? The one below me about the issue with Zigbee and BLE.

    Not really, that is strange, can you repost the question about Zigbee and BLE? I do not find your specific question regarding the issue with this combo. 

  • Hello Susheel,

    Right now I am working in different features of the code so I couldn't try what you said. As soon as possible, I will try what you told me.

    Meanwhile, the question I was referring was the following

    I have tried to follow the path why BLE and UART are not compatible and I have found that they can be compatible, but once some time has passed, the UART communication ends and BLE and Zigbee start working as usual.

Reply
  • Hello Susheel,

    Right now I am working in different features of the code so I couldn't try what you said. As soon as possible, I will try what you told me.

    Meanwhile, the question I was referring was the following

    I have tried to follow the path why BLE and UART are not compatible and I have found that they can be compatible, but once some time has passed, the UART communication ends and BLE and Zigbee start working as usual.

Children
  • I have asked the Zigbee expert to shed some light on the BLE, Zigbee and UART compatibility. She is on holiday today but will respond most likely on Tuesday as Monday is also holiday (Norwegian National Day)

  • I am now talked to the Zigbee developer in support and she says that she does not see any reason that UART will have any compatibility issues when used with BLE and Zigbee. There is also a BLE UART/Zigbee doorlock, that uses uart gor logging.

    there is also a template you should follow if you wants to run both BLE and Zigbee, adding UART peripheral to this example and then the rest of his application will be much easier for you than adding BLE to an existing Zigbee project:
  • Hello Susheel!

    There is also a BLE UART/Zigbee doorlock, that uses uart gor logging.

    I think the example you said is the same example I am using as a guide for my project. In fact, what I am trying to make is a Zigbee doorlock but with a lot of features. That example uses NUS for sending data over BLE, could that be my problem?

     I've been trying unsuccesfully to add uart communication to the template you mention but I am not able to do it. I am using the same code that is working in my current board (with BLE and Zigbee deactivated) but it refuses to work. Below I show yo the code I am using (it is written in spanish, sorry):

    void uart_event_handle(app_uart_evt_t * p_event)
    {
        static uint8_t buffer[LONGITUD_MAX_MENSAJE];
        static uint8_t index = 0;
        uint32_t err_code;
    
        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:
                UNUSED_VARIABLE(app_uart_get(&buffer[index]));
                if ((buffer[index] == 0x0a) || (buffer[index] == 0x0d) || index >= LONGITUD_MAX_MENSAJE)
                {
                    // Do something
                    index = 0;
                }
                else
                {
                    index++;
                }
                break;
    
            default:
                break;
        }
    }
    
    
    static void uart_init(void)
    {
        uint32_t err_code;
        app_uart_comm_params_t const comm_params =
        {
            .rx_pin_no    = RX_PIN,
            .tx_pin_no    = TX_PIN,
            .rts_pin_no   = RTS_PIN,
            .cts_pin_no   = CTS_PIN,
            .flow_control = FLOW_CONTROL,
            .use_parity   = USE_PARITY,
            .baud_rate    = BAUDRATE
        };
    
        APP_UART_INIT(&comm_params,
                      uart_event_handle,
                      APP_IRQ_PRIORITY_HIGH,
                      err_code);
    
        APP_ERROR_CHECK(err_code);
    }

    I also modified the sdk_config file to define UART_ENABLED to 1 and used the APP_UART_DRIVER_INSTANCE 0, the sdk_donfig file is pretty similar to mine. But I don't discard that the error may be in that file.

    Cheers!

    EDIT: I realised that the problem was having both the log and the uart, so I commented out the initialisation function for the log and everything seems to work. I have yet to test the full functionality, but it looks promising.

  • Hello Susheel!

    I have continued and realised the cause of the error. I am posting the info in case someone else has the same problem in the future.

    After a week of debugging, I find out that the library "libzboss.ed.a" located in "external/zboss/lib/gcc/" was causing the code to fail. If I use the "libzboss.a" library instead of the "libzboss.ed.a" (note the difference between .ed.a and just .a) it works like a charm.

    In fact, as Susheel told me, there is no incompatibilities between Zigbee and UART. And I simply changed that library and everything started working. There is also one little thing to modify, and that is to remove the "ZB_ED_ROLE" from the Preprocessor definitions, but if you don't do that, Segger (or whatever you use) will throw an error.

    To close the thread, I just want to know why was happening this error. I would appreciate it if someone could explain a bit more about why this problem is occurring.

    Cheers!

  • Hello again!

    I have been experiencing some problems with Serial and Zigbee communication. The previous solution I found about "libzboss.a" library is not suitable, that library is not used on Zigbee End Devices (I need to use libzboss.ed.a) so when I try to reconnect to my Coordinator it connects as a device with GreenPower cluster only (when I don't use it).

    Please, I need to fix this issue as soon as possible, it's been 3 months since the beginning of the question and I still have the UART working.

    Regards.

Related