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

App Timer tutorial, nrf_drv_clock_lfclk_request

I am debugging a small program for the nRF52, which uses the App Timer and communicates over UART. I am trying to keep up with bug fixes, and so I'm using SDK 11.0.

The UART works fine, my program prints a greeting in the first few lines of main(). But I don't seem to be setting up timer interrupts correctly, since the printing that is supposed to occur at each timer tick (every 5 seconds), in my timer handler function, is not taking place.

In order to get my program to compile at all, I had to write the LFCLK request in my timer configuration function as follows:

nrf_drv_clock_lfclk_request(false);

I copied that from an example somewhere, I'm not sure exactly where.

However, the App Timer tutorial shows that nrf_drv_clock_lfclk_request takes NO arguments. The function definition that I'm seeing wants a pointer to a nrf_drv_clock_handler_item_t.

I have to wonder why this discrepancy exists. It might be because the tutorial isn't written for SDK 11.0, but I don't know for sure. I also wonder whether my code in fact fails to start the LFCLK.

I will post my complete program if it helps. I thought that I would start with the first discrepancy I found before dumping 100 lines of code to the forums. Thanks for your help.

  • Following up to myself: I just discovered the function nrf_drv_clock_lfclk_is_running(). After executing this...

    err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(false);
    

    ...nrf_drv_clock_lfclk_is_running() returns FALSE. I have confirmed that I'm not starting LFCLK. From my reading, I think that nrf_drv_config.h and the Makefile may also affect the hardware. The App Timer tutorial says that App Timer uses RTC1. I have modified my nrf_drv_config.h to read:

    #define RTC1_ENABLED 1
    

    When RTC1 triggers, which software interrupt does it use? It might use SWI0, since the Makefile that comes with the App Time tutorial does not include the line:

    CFLAGS += -DSWI_DISABLE0
    

    I made sure that my Makefile also does not include this line. Any clues? Thanks again.

  • Hey.

    Documentation of the clock driver is found here.

    The rtc example shows how to set up the rtc, as referenced by the APP_TIMER_INIT documentation:

    This module assumes that the LFCLK is already running. If it is not, the module will be non-functional, since the RTC will not run. If you do not use a SoftDevice, you must start the LFCLK manually. See the rtc_example's lfclk_config() function for an example of how to do this. If you use a SoftDevice, the LFCLK is started on SoftDevice init.

    Let me know if you need some code snippets

    -Anders

    UPDATE 7 April. Trying it out on PCA10040 (nRF52 DK)

    I did the following, which let me print something periodically with a app_timer. It was compiled with Keil 5. I am not sure if this will help you or not, but at least we know that this works with the Keil compiler.

    1: Start with the example project "uart" found in "nRF5_SDK_11\examples\peripheral".

    2: include app_timer and clock headers. (and add the files to the include paths)

    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    

    3: define some timer variables

    #define APP_TIMER_PRESCALER             0                                           /**< Value of the RTC1 PRESCALER register. */
    #define APP_TIMER_OP_QUEUE_SIZE         4 
    

    4: Add the .c files to Keil (right click ->add existing files)

    5: Create a timer id

    APP_TIMER_DEF(periodic_print_id);
    

    6: Create clock setup and timer handler

    static void periodic_print(void * p_context){
        printf("\n Periodic print: \n\r");
    }
    
    static void lfclk_config(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_clock_lfclk_request(NULL);
    }
    

    7: Edit main to initialize and start the timer task.

        lfclk_config();
        APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
        err_code = app_timer_create(&periodic_print_id, APP_TIMER_MODE_REPEATED, periodic_print);
        APP_ERROR_CHECK(err_code);
        err_code = app_timer_start(periodic_print_id, APP_TIMER_TICKS(500, APP_TIMER_PRESCALER),NULL);
        APP_ERROR_CHECK(err_code);
    
  • Thanks for your reply, Anders. I thought that the purpose of the App Timer was to provide a higher-level interface than the RTC, and to make using multiple timers easy (I will eventually need two)? Does my App Timer code still need to reference the lower-level RTC functions?

    In any case: the lfclk_config() in the SDK11 RTC example reads thus:

    ret_code_t err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);
    

    My own code is nearly identical, the only difference is that I declare err_code on an earlier line. The App Timer tutorial shows nrf_drv_clock_lfclk_request being called with no arguments. Consistent with the SDK11 docs, that doesn't work for me. I get a compiler error because nrf_drv_clock_lfclk_request wants a pointer to a nrf_drv_clock_handler_item_t (NULL, or false, substitutes when you don't need a callback function).

  • app_timer uses SWI0 to send timer interrupts to the application timer handler.

  • Are you using the nRF52 Development kit, or a custom board? If DK, which version?

Related