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

nrf_gfx_init causes RTC1 interrupts to stop from being called?

I'm using SDK 15.0.0 on nRF52832_xxaa.

I'm currently using RTC1 as a low frequency timer to keep track of time elapsed while my device is sleeping. This works well and I get a pretty accurate interrupt seven times a second to increment time elapsed. I've used this same code on a few projects (sdk 12.3.0 with nRF51 and sdk 15 nRF52) without issue.

However I am now using the nrf gfx library with an LCD screen that has an ST7735S controller. On calling nrf_gfx_init, the RTC1 interrupt handler stops from being called. After this, I can call nrf_gfx_uninit and the RTC1 handler is called and works as intended. I first initialize the RTC1 timer and then some time later initialize gfx driver.

I can't seem to find any information about this online and if this is expected behavior. Not sure what further information I can provide than this, so I'm really looking for some information on how the two may be interfering with each other so I have some idea of what to investigate.

FWIW here is my RTC init function:

static STATUS_t _timer_rtc_init (void)
{
  ret_code_t err_code = nrf_drv_clock_init();
  APP_ERROR_CHECK(err_code);
  nrf_drv_clock_lfclk_request(NULL);

  // Initialize RTC instance
  nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
  config.prescaler = TIMER_RTC_PRESCALER;
  err_code = nrf_drv_rtc_init(&rtc, &config, _timer_rtc_handler);
  APP_ERROR_CHECK(err_code);

  // Enable tick event & interrupt
  nrf_drv_rtc_tick_enable(&rtc, true);

  // Power on RTC instance
  nrf_drv_rtc_enable(&rtc);

  return (STATUS_OK);
}

  • Hello,

    I tried the gfx example with this modified main.c file, using the rtc. 

    /**
     * Copyright (c) 2017 - 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.
     * 
     * 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
     * @brief TFT Example Application main file.
     *
     * This file contains the source code for a sample application using the
     * GFX library based on the ILI9341 controller.
     *
     */
    
    #include "nrf_gfx.h"
    #include "nrf52_dk.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrf_drv_clock.h"
    #include "nrf_drv_rtc.h"
    
    #define COMPARE_COUNTERTIME  (3UL)                                        /**< Get Compare event COMPARE_TIME seconds after the counter starts from 0. */
    
    #ifdef BSP_LED_0
        #define TICK_EVENT_OUTPUT     BSP_LED_0                                 /**< Pin number for indicating tick event. */
    #endif
    #ifndef TICK_EVENT_OUTPUT
        #error "Please indicate output pin"
    #endif
    #ifdef BSP_LED_1
        #define COMPARE_EVENT_OUTPUT   BSP_LED_1                                /**< Pin number for indicating compare event. */
    #endif
    #ifndef COMPARE_EVENT_OUTPUT
        #error "Please indicate output pin"
    #endif
    
    
    #define GRAY            0xC618
    #define RED             0xF800
    #define BLUE            0x001F
    
    #define LINE_STEP       10
    
    #define CIRCLE_RADIUS   10
    #define CIRCLE_STEP     ((2 * CIRCLE_RADIUS) + 1)
    
    #define BORDER          2
    
    const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC0. */
    
    
    static volatile bool gfx_enabled = false;
    
    static const char * test_text = "nRF52 family";
    
    extern const nrf_gfx_font_desc_t orkney_24ptFontInfo;
    extern const nrf_lcd_t nrf_lcd_ili9341;
    extern const nrf_lcd_t nrf_lcd_st7735;
    
    static const nrf_gfx_font_desc_t * p_font = &orkney_24ptFontInfo;
    static const nrf_lcd_t * p_lcd = &nrf_lcd_ili9341;
    
    static void gfx_initialization(void)
    {
        APP_ERROR_CHECK(nrf_gfx_init(p_lcd));
    }
    
    static void brackground_set(void)
    {
        nrf_gfx_invert(p_lcd, true);
        nrf_gfx_background_set(p_lcd, nrf52);
        nrf_gfx_invert(p_lcd, false);
    }
    
    static void text_print(void)
    {
        nrf_gfx_point_t text_start = NRF_GFX_POINT(5, nrf_gfx_height_get(p_lcd) - 50);
        APP_ERROR_CHECK(nrf_gfx_print(p_lcd, &text_start, 0, test_text, p_font, true));
    }
    
    static void screen_clear(void)
    {
        nrf_gfx_screen_fill(p_lcd, GRAY);
    }
    
    static void line_draw(void)
    {
        nrf_gfx_line_t my_line = NRF_GFX_LINE(0, 0, 0, nrf_gfx_height_get(p_lcd), 2);
        nrf_gfx_line_t my_line_2 = NRF_GFX_LINE(nrf_gfx_width_get(p_lcd), nrf_gfx_height_get(p_lcd), 0, nrf_gfx_height_get(p_lcd), 1);
    
        for (uint16_t i = 0; i <= nrf_gfx_width_get(p_lcd); i += LINE_STEP)
        {
            my_line.x_end = i;
            APP_ERROR_CHECK(nrf_gfx_line_draw(p_lcd, &my_line, RED));
        }
    
        my_line.x_end = nrf_gfx_width_get(p_lcd);
    
        for (uint16_t i = 0; i <= nrf_gfx_height_get(p_lcd); i += LINE_STEP)
        {
            my_line.y_end = (nrf_gfx_height_get(p_lcd) - i);
            APP_ERROR_CHECK(nrf_gfx_line_draw(p_lcd, &my_line, RED));
        }
    
        for (uint16_t i = 0; i <= nrf_gfx_height_get(p_lcd); i += LINE_STEP)
        {
            my_line_2.y_end = (nrf_gfx_height_get(p_lcd) - i);
            APP_ERROR_CHECK(nrf_gfx_line_draw(p_lcd, &my_line_2, BLUE));
        }
    
        my_line_2.y_end = 0;
    
        for (uint16_t i = 0; i <= nrf_gfx_width_get(p_lcd); i += LINE_STEP)
        {
            my_line_2.x_end = i;
            APP_ERROR_CHECK(nrf_gfx_line_draw(p_lcd, &my_line_2, BLUE));
        }
    }
    
    static void circle_draw(void)
    {
        nrf_gfx_circle_t my_circle = NRF_GFX_CIRCLE(0, 0, CIRCLE_RADIUS);
    
        for (uint16_t j = 0; j <= nrf_gfx_height_get(p_lcd); j += CIRCLE_STEP)
        {
            my_circle.y = j;
            for (uint16_t i = 0; i <= nrf_gfx_width_get(p_lcd); i += CIRCLE_STEP)
            {
                my_circle.x = i;
                APP_ERROR_CHECK(nrf_gfx_circle_draw(p_lcd, &my_circle, BLUE, true));
            }
        }
    
        for (uint16_t j = CIRCLE_RADIUS; j <= nrf_gfx_height_get(p_lcd) + CIRCLE_RADIUS; j += CIRCLE_STEP)
        {
            my_circle.y = j;
            for (uint16_t i = CIRCLE_RADIUS; i <= nrf_gfx_width_get(p_lcd) + CIRCLE_RADIUS; i += CIRCLE_STEP)
            {
                my_circle.x = i;
                APP_ERROR_CHECK(nrf_gfx_circle_draw(p_lcd, &my_circle, RED, false));
            }
        }
    }
    
    static void rect_draw(void)
    {
        nrf_gfx_rect_t my_rect = NRF_GFX_RECT(nrf_gfx_width_get(p_lcd) / 2,
                                 nrf_gfx_height_get(p_lcd) / nrf_gfx_width_get(p_lcd),
                                 nrf_gfx_height_get(p_lcd),
                                 BORDER);
        nrf_gfx_rect_t my_rect_fill = NRF_GFX_RECT(nrf_gfx_width_get(p_lcd) / 2,
                                      nrf_gfx_height_get(p_lcd) / nrf_gfx_width_get(p_lcd),
                                      nrf_gfx_height_get(p_lcd),
                                      BORDER);
    
        nrf_gfx_rotation_set(p_lcd, NRF_LCD_ROTATE_90);
    
        for (uint16_t i = 0, j = 0;
            i <= (nrf_gfx_width_get(p_lcd) - (2 * BORDER)) / 2 &&
            j <= (nrf_gfx_height_get(p_lcd) - (2 * BORDER)) / 2;
            i += 6, j += 8)
        {
            my_rect.x = i;
            my_rect.y = j;
            my_rect_fill.x = i + BORDER;
            my_rect_fill.y = j + BORDER;
            my_rect.width = nrf_gfx_width_get(p_lcd) - i * 2;
            my_rect.height = nrf_gfx_height_get(p_lcd) - j * 2;
            my_rect_fill.width = nrf_gfx_width_get(p_lcd) - i * 2 - (2 * BORDER);
            my_rect_fill.height = nrf_gfx_height_get(p_lcd) - j * 2 - (2 * BORDER);
    
            // Draw using pseudo-random colors.
            APP_ERROR_CHECK(nrf_gfx_rect_draw(p_lcd, &my_rect, 2, ((i + j) * 10), false));
            APP_ERROR_CHECK(nrf_gfx_rect_draw(p_lcd, &my_rect_fill, 2, (UINT16_MAX - (i + j) * 10), true));
        }
    
        nrf_gfx_rotation_set(p_lcd, NRF_LCD_ROTATE_0);
    
    }
    
    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        NRF_LOG_INFO("interrupt");
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
            nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
            gfx_initialization();
            NRF_LOG_INFO("gfx!");
        }
        else if (int_type == NRF_DRV_RTC_INT_TICK)
        {
            nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
        }
    }
    
    static ret_code_t _timer_rtc_init (void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
        nrf_drv_clock_lfclk_request(NULL);
    
        // Initialize RTC instance
        nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
        config.prescaler = 4095; //TIMER_RTC_PRESCALER;
        err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
        APP_ERROR_CHECK(err_code);
    
        // Enable tick event & interrupt
        nrf_drv_rtc_tick_enable(&rtc, true);
        
        //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
        err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
        APP_ERROR_CHECK(err_code);
    
        // Power on RTC instance
        nrf_drv_rtc_enable(&rtc);
    
        return (NRF_SUCCESS);
    }
    
    void gfx_action(void)
    {
        while (1)
        {
           brackground_set();
           text_print();
           nrf_delay_ms(1000);
           screen_clear();
           line_draw();
           nrf_delay_ms(1000);
           screen_clear();
           circle_draw();
           nrf_delay_ms(1000);
           screen_clear();
           rect_draw();
           nrf_delay_ms(1000);
        }
    }
    
    int main(void)
    {
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("GFX usage example application started.")
        NRF_LOG_FLUSH();
    
        
        bsp_board_init(BSP_INIT_LEDS);
        _timer_rtc_init();
        
        NRF_LOG_INFO("init complete");
        
        while(1)
        {
            NRF_LOG_FLUSH();
            if (gfx_enabled)
            {
                gfx_action();
            }
            __SEV();
            __WFE();
            __WFE();
        }
        
        /*gfx_initialization();
    
        while (1)
        {
           brackground_set();
           text_print();
           nrf_delay_ms(1000);
           screen_clear();
           line_draw();
           nrf_delay_ms(1000);
           screen_clear();
           circle_draw();
           nrf_delay_ms(1000);
           screen_clear();
           rect_draw();
           nrf_delay_ms(1000);
        }*/
    }
    
    

    I toggle one of the LEDs after starting the gfx library, and it still toggles. Are you sure there aren't anything else that happens? Maybe your application gets caught in an error handler?

    BR,

    Edvin

  • Thank you for taking the time to test this!

    I can confirm that this is working in a new project. On further inspection with the original project, we had set the MISO pin for the ST7735 in sdk_config to 0, which it turns out is the pin for the LF oscillator. We don't actually have a MISO pin for our screen so 0 was used and forgotten about. This must have redirected input from the oscillator to spi when the spi initialization was called from the gfx library!

Related