timer4 accuracy

S in development environment :Windows7
HARD :(Taiyo Yuden)EBSHSN Series Evaluation Board : Central / Peripherals
CPU :(Nordic) nRF52832 / ARMR Cortex?-M4F 32 bit processor 28-pin Land Grid Array / 15GPIOs / SWD
Soft Ver:nRF5_SDK_15.2.0_9412b96
clock :RC transmission setting

I switched the terminal output to Low / Hi at 1-second intervals with two peripheral devices and checked whether the switching timing is synchronized,
but did not synchronize, please tell me how to synchronize

Thank you very much.

Parents
  • Hi,

    Assuming you have no problem with your SW implementation, the accuracy of the timer is given by the accuracy of the HF clock, which  is given by the clock source. If you use the internal RC oscillator (HFINT), the accuracy is at worst <±6 %. In other words very inaccurate, so you should always use the crystal oscillator (HFXO) when you need a decent accuracy. In that case the accuracy is given by the accuracy of the crystal you are using.

  • I switched from the CR oscillator (HFINT) to the 32.768 kHz crystal oscillator (HFXO) and checked the operation, but it was not synchronized.
    The contents of the timer settings will be attached, so please point out the mistake.
    Thank you very much.

    SAMPLE.c
    Source program excerpt on timer4 control
    ------------------------------------------------------------------------------------------
    << sdk_config.h (Excerpt of timer program) >>
    // <q> NRFX_TIMER4_ENABLED  - Enable TIMER4 instance
    #ifndef NRFX_TIMER4_ENABLED
    #define NRFX_TIMER4_ENABLED 0
    #endif
    
    // <o> TIMER_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
    // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    #ifndef TIMER_DEFAULT_CONFIG_IRQ_PRIORITY
    #define TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 6
    #endif
    
    // <q> TIMER4_ENABLED  - Enable TIMER4 instance
    #ifndef TIMER4_ENABLED
    #define TIMER4_ENABLED 1
    #endif
    
    //==========================================================
    
    // <h> Clock - SoftDevice clock configuration
    
    //==========================================================
    // <o> NRF_SDH_CLOCK_LF_SRC  - SoftDevice clock source.
    // <0=> NRF_CLOCK_LF_SRC_RC 
    // <1=> NRF_CLOCK_LF_SRC_XTAL 
    // <2=> NRF_CLOCK_LF_SRC_SYNTH 
    #ifndef NRF_SDH_CLOCK_LF_SRC
    #define NRF_SDH_CLOCK_LF_SRC 1
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. 
    #ifndef NRF_SDH_CLOCK_LF_RC_CTIV
    #define NRF_SDH_CLOCK_LF_RC_CTIV 0
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. 
    // <i> How often (in number of calibration intervals) the RC oscillator shall be calibrated
    // <i>  if the temperature has not changed.
    #ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV
    #define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_ACCURACY  - External clock accuracy used in the LL to compute timing.
    // <0=> NRF_CLOCK_LF_ACCURACY_250_PPM 
    // <1=> NRF_CLOCK_LF_ACCURACY_500_PPM 
    // <2=> NRF_CLOCK_LF_ACCURACY_150_PPM 
    // <3=> NRF_CLOCK_LF_ACCURACY_100_PPM 
    // <4=> NRF_CLOCK_LF_ACCURACY_75_PPM 
    // <5=> NRF_CLOCK_LF_ACCURACY_50_PPM 
    // <6=> NRF_CLOCK_LF_ACCURACY_30_PPM 
    // <7=> NRF_CLOCK_LF_ACCURACY_20_PPM 
    // <8=> NRF_CLOCK_LF_ACCURACY_10_PPM 
    // <9=> NRF_CLOCK_LF_ACCURACY_5_PPM 
    // <10=> NRF_CLOCK_LF_ACCURACY_2_PPM 
    // <11=> NRF_CLOCK_LF_ACCURACY_1_PPM 
    #ifndef NRF_SDH_CLOCK_LF_ACCURACY
    #define NRF_SDH_CLOCK_LF_ACCURACY 7
    #endif
    
    
    ------------------------------------------------------------------------------------------
    << boards.h (Excerpt of timer program) >>
    // Low frequency clock source to be used by the SoftDevice
    /*< Xtal clock setting >*/
    #define NRF_CLOCK_LFCLKSRC      {.source       = NRF_CLOCK_LF_SRC_XTAL,			\
    								 .rc_ctiv      = 0,								\
    								 .rc_temp_ctiv = 0,								\
    								 .accuracy     = NRF_CLOCK_LF_ACCURACY_20_PPM}
    
    								 
    ------------------------------------------------------------------------------------------
    << main.c (Excerpt of timer program) >>
    
    /** @brief Handler for timer4 (100us) events. */
    void timer4_event_handler(nrf_timer_event_t event_type, void* p_context)
    {
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE4:	/* timer 4 events */
                Control_counter ++;				/* Control_counter update */
    			Con_Com_tim ++;					/* BLE connection communication timer count */
                break;
    
            default:
                break;
        }
    }
    /**@brief Function for initializing the timer4 module. */
    static void Conterl_timer_init(void)
    {
        uint32_t time_ticks;
        uint32_t err_code = NRF_SUCCESS;
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        err_code = nrf_drv_timer_init(&Ctl_timer, &timer_cfg, timer4_event_handler);
        APP_ERROR_CHECK(err_code);
    
        time_ticks = nrf_drv_timer_us_to_ticks(&Ctl_timer, 100);
    
        nrf_drv_timer_extended_compare(
             &Ctl_timer, NRF_TIMER_CC_CHANNEL4, time_ticks, NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK, true);
    
    	Control_counter = 0;			/* 100us count reset */
    	Con_Com_tim = 0;				/* BLE connection communication timer reset */
    	nrf_drv_timer_enable(&Ctl_timer);
    }
    

  • Hi,

    there seems to be a misunderstanding here. The TIMER peripherals use the HF clock, so it has nothing to do with the 32.768 kHz oscillator. The timer will use the HFCLK, which use a HFINT (RC) or HFXO (32 MHz crystal) as reference. So to get an accurate TIMER, you nee to enable the HFXO.

    If you are testing without a SoftDevice, then you can simply enable it like this:

        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART    = 1;
    
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
        {
            // Do nothing while waiting for the clock to start
        }

    If you are using a SoftDevice you should call sd_clock_hfclk_request().

    In the end, if you want to make a clean solution that works with all other SDK drivers and libraries you should use the clock driver and call nrf_drv_clock_hfclk_request().

  • I am using the SDK.
    Please give a sample program using "nrf_drv_clock_hfclk_request ()".

  • Hi,

    Let me just first say that you can test this most simply by one of the two other methods I mentioned (which depends on if you are using SoftDevice or not).

    For using the driver, you can refer to for instance the examples\802_15_4\wireless_uart example in SDK 15.2 to see the necessary files, includes and sdk_config.h parameters.

    Summing up:

    If you don't have the clock driver configuration in your projects sdk_config.h, you should make sure to add it like this (adjust as needed):

    // <e> NRF_CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer
    //==========================================================
    #ifndef NRF_CLOCK_ENABLED
    #define NRF_CLOCK_ENABLED 1
    #endif
    // <o> CLOCK_CONFIG_LF_SRC  - LF Clock Source
     
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth 
    // <131073=> External Low Swing 
    // <196609=> External Full Swing 
    
    #ifndef CLOCK_CONFIG_LF_SRC
    #define CLOCK_CONFIG_LF_SRC 1
    #endif
    
    // <q> CLOCK_CONFIG_LF_CAL_ENABLED  - Calibration enable for LF Clock Source
     
    
    #ifndef CLOCK_CONFIG_LF_CAL_ENABLED
    #define CLOCK_CONFIG_LF_CAL_ENABLED 0
    #endif
    
    // <o> CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    
    // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef CLOCK_CONFIG_IRQ_PRIORITY
    #define CLOCK_CONFIG_IRQ_PRIORITY 6
    #endif
    

    The corresponding nrfx part will most likely already be there in your sdk_config.h, but if not, you should add this:

    //==========================================================
    // <e> NRFX_CLOCK_ENABLED - nrfx_clock - CLOCK peripheral driver
    //==========================================================
    #ifndef NRFX_CLOCK_ENABLED
    #define NRFX_CLOCK_ENABLED 1
    #endif
    // <o> NRFX_CLOCK_CONFIG_LF_SRC  - LF Clock Source
     
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth 
    // <131073=> External Low Swing 
    // <196609=> External Full Swing 
    
    #ifndef NRFX_CLOCK_CONFIG_LF_SRC
    #define NRFX_CLOCK_CONFIG_LF_SRC 1
    #endif
    
    // <o> NRFX_CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef NRFX_CLOCK_CONFIG_IRQ_PRIORITY
    #define NRFX_CLOCK_CONFIG_IRQ_PRIORITY 6
    #endif
    
    // <e> NRFX_CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module.
    //==========================================================
    #ifndef NRFX_CLOCK_CONFIG_LOG_ENABLED
    #define NRFX_CLOCK_CONFIG_LOG_ENABLED 0
    #endif
    // <o> NRFX_CLOCK_CONFIG_LOG_LEVEL  - Default Severity level
     
    // <0=> Off 
    // <1=> Error 
    // <2=> Warning 
    // <3=> Info 
    // <4=> Debug 
    
    #ifndef NRFX_CLOCK_CONFIG_LOG_LEVEL
    #define NRFX_CLOCK_CONFIG_LOG_LEVEL 3
    #endif
    
    // <o> NRFX_CLOCK_CONFIG_INFO_COLOR  - ANSI escape code prefix.
     
    // <0=> Default 
    // <1=> Black 
    // <2=> Red 
    // <3=> Green 
    // <4=> Yellow 
    // <5=> Blue 
    // <6=> Magenta 
    // <7=> Cyan 
    // <8=> White 
    
    #ifndef NRFX_CLOCK_CONFIG_INFO_COLOR
    #define NRFX_CLOCK_CONFIG_INFO_COLOR 0
    #endif
    
    // <o> NRFX_CLOCK_CONFIG_DEBUG_COLOR  - ANSI escape code prefix.
     
    // <0=> Default 
    // <1=> Black 
    // <2=> Red 
    // <3=> Green 
    // <4=> Yellow 
    // <5=> Blue 
    // <6=> Magenta 
    // <7=> Cyan 
    // <8=> White 
    
    #ifndef NRFX_CLOCK_CONFIG_DEBUG_COLOR
    #define NRFX_CLOCK_CONFIG_DEBUG_COLOR 0
    #endif
    
    // </e>

    Then make a function like this and call it from your main function where you initialize the system (after enabling the SoftDevice if it is being used):

    static void clock_init(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_MODULE_ALREADY_INITIALIZED));
    
        nrf_drv_clock_hfclk_request(NULL);
        while (!nrf_drv_clock_hfclk_is_running())
        {
            // spin lock
        }
    }

    Br,

    Einar

Reply
  • Hi,

    Let me just first say that you can test this most simply by one of the two other methods I mentioned (which depends on if you are using SoftDevice or not).

    For using the driver, you can refer to for instance the examples\802_15_4\wireless_uart example in SDK 15.2 to see the necessary files, includes and sdk_config.h parameters.

    Summing up:

    If you don't have the clock driver configuration in your projects sdk_config.h, you should make sure to add it like this (adjust as needed):

    // <e> NRF_CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer
    //==========================================================
    #ifndef NRF_CLOCK_ENABLED
    #define NRF_CLOCK_ENABLED 1
    #endif
    // <o> CLOCK_CONFIG_LF_SRC  - LF Clock Source
     
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth 
    // <131073=> External Low Swing 
    // <196609=> External Full Swing 
    
    #ifndef CLOCK_CONFIG_LF_SRC
    #define CLOCK_CONFIG_LF_SRC 1
    #endif
    
    // <q> CLOCK_CONFIG_LF_CAL_ENABLED  - Calibration enable for LF Clock Source
     
    
    #ifndef CLOCK_CONFIG_LF_CAL_ENABLED
    #define CLOCK_CONFIG_LF_CAL_ENABLED 0
    #endif
    
    // <o> CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    
    // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef CLOCK_CONFIG_IRQ_PRIORITY
    #define CLOCK_CONFIG_IRQ_PRIORITY 6
    #endif
    

    The corresponding nrfx part will most likely already be there in your sdk_config.h, but if not, you should add this:

    //==========================================================
    // <e> NRFX_CLOCK_ENABLED - nrfx_clock - CLOCK peripheral driver
    //==========================================================
    #ifndef NRFX_CLOCK_ENABLED
    #define NRFX_CLOCK_ENABLED 1
    #endif
    // <o> NRFX_CLOCK_CONFIG_LF_SRC  - LF Clock Source
     
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth 
    // <131073=> External Low Swing 
    // <196609=> External Full Swing 
    
    #ifndef NRFX_CLOCK_CONFIG_LF_SRC
    #define NRFX_CLOCK_CONFIG_LF_SRC 1
    #endif
    
    // <o> NRFX_CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef NRFX_CLOCK_CONFIG_IRQ_PRIORITY
    #define NRFX_CLOCK_CONFIG_IRQ_PRIORITY 6
    #endif
    
    // <e> NRFX_CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module.
    //==========================================================
    #ifndef NRFX_CLOCK_CONFIG_LOG_ENABLED
    #define NRFX_CLOCK_CONFIG_LOG_ENABLED 0
    #endif
    // <o> NRFX_CLOCK_CONFIG_LOG_LEVEL  - Default Severity level
     
    // <0=> Off 
    // <1=> Error 
    // <2=> Warning 
    // <3=> Info 
    // <4=> Debug 
    
    #ifndef NRFX_CLOCK_CONFIG_LOG_LEVEL
    #define NRFX_CLOCK_CONFIG_LOG_LEVEL 3
    #endif
    
    // <o> NRFX_CLOCK_CONFIG_INFO_COLOR  - ANSI escape code prefix.
     
    // <0=> Default 
    // <1=> Black 
    // <2=> Red 
    // <3=> Green 
    // <4=> Yellow 
    // <5=> Blue 
    // <6=> Magenta 
    // <7=> Cyan 
    // <8=> White 
    
    #ifndef NRFX_CLOCK_CONFIG_INFO_COLOR
    #define NRFX_CLOCK_CONFIG_INFO_COLOR 0
    #endif
    
    // <o> NRFX_CLOCK_CONFIG_DEBUG_COLOR  - ANSI escape code prefix.
     
    // <0=> Default 
    // <1=> Black 
    // <2=> Red 
    // <3=> Green 
    // <4=> Yellow 
    // <5=> Blue 
    // <6=> Magenta 
    // <7=> Cyan 
    // <8=> White 
    
    #ifndef NRFX_CLOCK_CONFIG_DEBUG_COLOR
    #define NRFX_CLOCK_CONFIG_DEBUG_COLOR 0
    #endif
    
    // </e>

    Then make a function like this and call it from your main function where you initialize the system (after enabling the SoftDevice if it is being used):

    static void clock_init(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();
        ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_MODULE_ALREADY_INITIALIZED));
    
        nrf_drv_clock_hfclk_request(NULL);
        while (!nrf_drv_clock_hfclk_is_running())
        {
            // spin lock
        }
    }

    Br,

    Einar

Children
  • After confirming that the settings in "sdk_config.h" were as instructed and adding "static void clock_init (void)",
    a warning was generated in "SEGGER_RTT_Syscalls_SES.C" because it was undefined. Please tell me how to fix it. I will attach a warning screen. Thanking you in advance.




    Postscript:
    I use the following features
    1) Peripheral wireless communication
    2) AD conversion (2 channels)
    3) Timer count
    4) Key detection
    No problem?
  • Hi,

    You get "implicit declaration" errors for the clock driver functions you are calling. This is probably because you have forgotten to include nrf_drv_clock.h in your main.c.

Related