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

UART and Timer conflict

I am using SDK12 with nrf52832.  UART working fine (with FIFO)  and Timer1 also works.

I wanted to set a 1 minute timeout around the UART dialog to handle disconnection etc. 

However, if I enable Timer1 when waiting for a response from the UART the timer responds as expected but the responses from the UART no longer occur.  Specifically, the UART's event handler is no longer called.

This looks like some kind of a conflict but I'm not sure where and why?

Thx.

Parents
  • Hello,

    What SDK version do you use? Is the problem that the event handler does not get called? If you could attach the project, I could take a look at it.

     

    Best regards,

    Edvin

  • I have the same on SDK 12.2 with armgcc. My board is non-standard but the issue seems to be exactly the same.

  • I get the problem when I have no blocking code.   Maybe I'll have to do a reduced version after all.

  • There were a few things. First, your timer config was not set, which uses the default TIMER4 values from nrf_drv_config.h. On timer 4, this was set to a 16bit timer, so you would not get the 10µs that you intended. Or actually, you would, but if you want to be able to see it, you will need a larger bit width. Changed it to 32. Change back if you feel like it.

    Also, I changed the pin you toggled, to be able to see the toggling (P0.17 = LED_0). Change back if you please.

    Then there was a while loop in your timer_init() function, which meant it never reached the end of this function. Not a problem in itself, but if you want to add something after timer_init(), this should be moved to the end of main().

    If you want to see a string repeated on the uart (more than a character) you need to have the while(app_uart_get/put) in a while loop. Please see the attached main.c file, and try to replace the main.c in your project with this one.

     

    If you want a more dynamic uart, you should look into how it is done in the ble_app_uart example, which uses an event handler for the uart as well.

    Also, if you are in the early development stage, I would recommend to move to a newer SDK (14 or 15).

     

    /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
     *
     * The information contained herein is property of Nordic Semiconductor ASA.
     * Terms and conditions of usage are described in detail in NORDIC
     * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
     *
     * Licensees are granted free, non-transferable use of the information. NO
     * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
     * the file.
     *
     */
    
    /** @file
     * @defgroup uart_example_main main.c
     * @{
     * @ingroup uart_example
     * @brief UART Example Application main file.
     *
     * This file contains the source code for a sample application using UART.
     * 
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include "app_error.h"
    #include "app_uart.h"
    #include "bsp.h"
    #include "nrf.h"
    #include "nrf_delay.h"
    
    #include <string.h>
    #include "app_error.h"
    #include "app_util_platform.h"
    #include "boards.h"
    #include "nrf_delay.h"
    #include "nrf_drv_spi.h"
    #include "nrf_gpio.h"
    #define NRF_LOG_MODULE_NAME "APP"
    #include "nrf_drv_timer.h"
    #include "nrf_log.h"
    
    //parameter for getting index of data array
    int p = 0;
    
    #define US_TSET_PIN 17          // CHANGED THIS to see the LED toggle
    const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(4);
    
    #define SPI_INSTANCE 1 /**< SPI instance index. */
    #ifndef SPI_SS_PIN
    #define SPI_SS_PIN 29
    #endif
    
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */
    static volatile bool       spi_xfer_done;                            /**< Flag used to indicate that SPI instance completed the transfer. */
    
    void spi_event_handler(nrf_drv_spi_evt_t const* p_event)
    {
        spi_xfer_done = true;
    }
    
    void spi_init(void)
    {
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG(1);
        spi_config.ss_pin               = SPI_SS_PIN;
        spi_config.miso_pin             = SPI1_CONFIG_MISO_PIN;
        spi_config.mosi_pin             = SPI1_CONFIG_MOSI_PIN;
        spi_config.sck_pin              = SPI1_CONFIG_SCK_PIN;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));
    }
    
    //#define ENABLE_LOOPBACK_TEST  /**< if defined, then this example will be a loopback test, which means that TX should be connected to RX to get data loopback. */
    
    #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 256      /**< UART RX buffer size. */
    
    void uart_error_handle(app_uart_evt_t* p_event)
    {
        if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
        {
            APP_ERROR_HANDLER(p_event->data.error_communication);
        }
        else if (p_event->evt_type == APP_UART_FIFO_ERROR)
        {
            APP_ERROR_HANDLER(p_event->data.error_code);
        }
    }
    
    void uart_init()
    {
        uint32_t                     err_code;
        const app_uart_comm_params_t comm_params =
            {
                RX_PIN_NUMBER,
                TX_PIN_NUMBER,
                RTS_PIN_NUMBER,
                CTS_PIN_NUMBER,
                APP_UART_FLOW_CONTROL_DISABLED,
                false,
                UART_BAUDRATE_BAUDRATE_Baud115200};
    
        APP_UART_FIFO_INIT(&comm_params,
                           UART_RX_BUF_SIZE,
                           UART_TX_BUF_SIZE,
                           uart_error_handle,
                           APP_IRQ_PRIORITY_LOW,
                           err_code);
    
        APP_ERROR_CHECK(err_code);
    }
    
    #ifdef ENABLE_LOOPBACK_TEST
    /** @brief Function for setting the @ref ERROR_PIN high, and then enter an infinite loop.
     */
    static void show_error(void)
    {
        LEDS_ON(LEDS_MASK);
        while (true)
        {
            // Do nothing.
        }
    }
    
    /** @brief Function for testing UART loop back. 
     *  @details Transmitts one character at a time to check if the data received from the loopback is same as the transmitted data.
     *  @note  @ref TX_PIN_NUMBER must be connected to @ref RX_PIN_NUMBER)
     */
    /*static void uart_loopback_test()      // Not used
    {
        uint8_t * tx_data = (uint8_t *)("\n\rLOOPBACK_TEST\n\r");
        uint8_t   rx_data;
    
        // Start sending one byte and see if you get the same
        for (uint32_t i = 0; i < MAX_TEST_DATA_BYTES; i++)
        {
            uint32_t err_code;
            while(app_uart_put(tx_data[i]) != NRF_SUCCESS);
    
            nrf_delay_ms(10);
            err_code = app_uart_get(&rx_data);
    
            if ((rx_data != tx_data[i]) || (err_code != NRF_SUCCESS))
            {
                show_error();
            }
        }
        return;
    }*/
    
    #endif
    void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
    {
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE0:
                NRF_TIMER4->EVENTS_COMPARE[0] = 0;
                nrf_gpio_pin_toggle(US_TSET_PIN);
                break;
    
            default:
                //Do nothing.
                break;
        }
    }
    void timer_init()
    {
        uint32_t err_code = NRF_SUCCESS;
        nrf_gpio_cfg_output(US_TSET_PIN);
    
        nrf_gpio_pin_set(US_TSET_PIN);
    
        //Configure all leds on board.
        LEDS_CONFIGURE(LEDS_MASK);
        LEDS_OFF(LEDS_MASK);
    
        //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
        nrf_drv_timer_config_t timer_config;
        timer_config.bit_width          = NRF_TIMER_BIT_WIDTH_32;       // had to set this because if timer_config is NULL, the defaults from nrf_drv_config.h is used, which sets bit width to 16.
        timer_config.frequency          = NRF_TIMER_FREQ_16MHz;         // the rest of timer_config settings are equivalent to default settings of TIMER4 in nrf_drv_config.h
        timer_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;
        timer_config.mode               = NRF_TIMER_MODE_TIMER;
        timer_config.p_context          = NULL;
        err_code = nrf_drv_timer_init(&TIMER_LED, &timer_config/*NULL*/, timer_led_event_handler);
        APP_ERROR_CHECK(err_code);
        uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
        uint32_t time_ticks;
        time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
    
        nrf_drv_timer_extended_compare(
            &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    
        nrf_drv_timer_enable(&TIMER_LED);
    
    /*    while (1)             //REMOVE THIS. gets stuck in a while loop.
        {
            __WFI();
        }*/
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        timer_init();
        uart_init();
    
        while (1)
        {
            uint8_t cr;
            while (app_uart_get(&cr) != NRF_SUCCESS);
            while (app_uart_put(cr) != NRF_SUCCESS);
        }
    }
    
    /** @} */
    

     

    Best regards,

    Edvin

     

  • Could you please check the file I added for ?

    If not, could you specify the issue? 

     

    BR,

    Edvin

  • Thx @Edvin and sorry for my delay in replying.

    OK. Finally got some time to look into this but having issues with compilation.

    I put your code in a copy of examples/uart.

    Using SDK14 for pca10040.

    I took the config from examples/uart
    + added to Makefile: $(SDK_ROOT)/components/drivers_nrf/timer/nrf_drv_timer.c \

    I get...

    In file included from ../../../../../../components/libraries/util/app_error.h:58:0,
    from ../../../main.c:26:
    ../../../../../../components/libraries/experimental_log/src/nrf_log_internal.h:105:38: error: pasting "m_nrf_log_" and ""APP"" does not give a valid preprocessing token
    #define NRF_LOG_MODULE_DATA CONCAT_3(m_nrf_log_,NRF_LOG_MODULE_NAME,_logs_data)
    ^
    ../../../../../../components/libraries/util/nordic_common.h:133:31: note: in definition of macro 'CONCAT_3_'
    #define CONCAT_3_(p1, p2, p3) p1##p2##p3

    Presumably there are other things i need to do to my config?

    May I have a copy of the config file you are using pls and anything else I need to change.

Reply
  • Thx @Edvin and sorry for my delay in replying.

    OK. Finally got some time to look into this but having issues with compilation.

    I put your code in a copy of examples/uart.

    Using SDK14 for pca10040.

    I took the config from examples/uart
    + added to Makefile: $(SDK_ROOT)/components/drivers_nrf/timer/nrf_drv_timer.c \

    I get...

    In file included from ../../../../../../components/libraries/util/app_error.h:58:0,
    from ../../../main.c:26:
    ../../../../../../components/libraries/experimental_log/src/nrf_log_internal.h:105:38: error: pasting "m_nrf_log_" and ""APP"" does not give a valid preprocessing token
    #define NRF_LOG_MODULE_DATA CONCAT_3(m_nrf_log_,NRF_LOG_MODULE_NAME,_logs_data)
    ^
    ../../../../../../components/libraries/util/nordic_common.h:133:31: note: in definition of macro 'CONCAT_3_'
    #define CONCAT_3_(p1, p2, p3) p1##p2##p3

    Presumably there are other things i need to do to my config?

    May I have a copy of the config file you are using pls and anything else I need to change.

Children
  • Did you include the path to the nrf_drv_timer.h file? Also, did you enable the timer in sdk_config.h?

    There are many things that are changed between SDK12 and SDK14, so I don't think you will be able to run the main.c code here in SDK14. I changed some parts (removed the SPI) and changed sdk_config.h, which decides what peripherals that are activated.

    uart+timer.zip

    Try to unzip the attached project so that you get the path:

    SDK14.0.0\examples\peripheral\timer+uart\pca10040\armgcc\makefile

    Then run cmd from the armgcc folder, and run:

    "make clean && make -j3 && nrfjprog -e && nrfjprog --program _build\nrf52832_xxaa.hex --verify && nrfjprog --reset"

    When the DK is connected. You should see that LED1 starts blinking, and it should echo everything it receives on UART (using the USB and a UART terminal).

  • Thx Edvin,

    (I did include the path to nrf_drv_timer.h but never mind)

    I am now using your latest setup.

    It compiles OK and the timer is working

    However, for some reason the terminal is not echoing.  I'm using macos screen at 115200.

    (I have wondered in the past whether this a reasonable way to work with the pca10040 uart?)

    So I commented out timer_int() and then the terminal works.

    This is telling me that the timer/uart conflict remains

    Regards, Paul

  • do you have any settings on your terminal?

    In my UART terminal, I have:

    115200 Baudrate,

    8 data bits,

    1 stop bit,

    parity none,

    flow control none

    Append LF (this one shouldn't matter)

     

     

    If you try to change the timeout handler to this, will you see the '1's printed on the terminal then?

            case NRF_TIMER_EVENT_COMPARE0:
                NRF_TIMER4->EVENTS_COMPARE[0] = 0;
                nrf_gpio_pin_toggle(US_TSET_PIN);
    			uint8_t cr = '1';
    			while (app_uart_put(cr) != NRF_SUCCESS);
                break;

     

    BR,

    Edvin

  • OK that works so output to the terminal is OK.
    ... and strangely input is now working too.  I must have been mistaken when I first tried this or the port got stuck somehow.

    So we're almost there.  I just need to port this back or, better, my main body of code forward from SDK 12_2.

    What's the best way to review what changes are going to be necessary?

    Many thx.

    Regards, Paul

  • Can you please try the application with another UART terminal? Maybe if you have access to a windows computer, can you try to use the Termite terminal? I also see some weird behavior on Putty, but I am not familiar with the settings in this terminal.

     

    The project is working. If you want confirmation, you can try to connect the UART to something else, like another DK, (pin P0.06 and P0.08), 

    BR,

    Edvin

Related