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 Reply
  • Ok,

    So the problem is not that nothing is working when you enable the uart. The problem is that when you enable the uart (I assume that you mean the part between the comments:

    // uart test

        ...

    // uart test done

    ?

     

    The call:

    while(app_uart_get(&cr) != NRF_SUCCESS);

    is a blocking call. When you include this, then nothing will happen before you get a character on the uart. You can test this by sending a character on the uart. Disable the flow control in uart_init() first, as many UART terminals for computers are not too god at handling flow control.

     

    Best regards,

    Edvin

Children
  • The problem is: when I init the timer, I assume it's a endless loop as its _WFI() functions.

    Then I try to comment this part, then I init the UART to get exact strings I send.

    The UART test code should be:

    while(app_uart_get(&cr)!=NRF_SUCCESS);

    while(app_uart_put(cr)!=NRF_SUCCESS);

    I made some changes before I upload the code...And it seems I mistakenly deleted the following line.

  • 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

     

Related