Unable to force use of external 32M HFXO using S132 SDK v7.0.1

I am using v7.0.1 S132 SDK on the nRF52832 processor for BlueTooth Light coded in Segger.

I have a high speed output (50uS) to drive an external device using an internal timer (timer[3]).

There seems to be jitter on the GPIO output.

Many posts seem to refer to forcing the use of the external 32MHz crystal using sd_clock_hfclk_request();

But querying the state using sd_clock_hfclk_is_running(p_is_running); never returns true.

I know the HF clock is running because I'm using the 16MHz clock for the timer (and using the radio to send BLE pkts).

How do I know which clock (INT or XO) is being used?

How do I force it to use the external 32MHz crystal?

Code Snippets
NOTE: The timer works but has Jitter

==============================================================================
// Main() startup calls for BLE using SDK S132 v7.0.1
	// 1) HFXO Startup fails here
	// Basic startup
    log_init();
    timers_init();  // Application timers in OS (1Hz)
    buttons_leds_init(&erase_bonds);
    power_management_init();
	// BLE Startup
    ble_stack_init();
    memset(&mac_addr, 0, sizeof(mac_addr));
    sd_ble_gap_addr_get(&mac_addr);
    gap_params_init();
    gatt_init();
    advertising_init();
    services_init();
    conn_params_init();
    peer_manager_init();
	init_my_timer();
	// 2) HFXO Startup fails here
    application_timers_start();
    advertising_start(erase_bonds);
	// 3) HFXO Startup fails here
	
==============================================================================
// Attempt to start the HFClock using HFXO
//  Fails in all 3 locations above
//  The while loop never quits ???

static uint32_t * p_is_running;
    sd_clock_hfclk_is_running(p_is_running);
    if (!p_is_running){
        //NRF_CLOCK->TASKS_HFCLKSTART = 1;

        sd_clock_hfclk_request();   // Force the use of the external HFXO?
        while (!p_is_running) 
            sd_clock_hfclk_is_running(p_is_running);
    }

==============================================================================
//  Timer init code
static const nrf_drv_timer_t m_timer3 = NRF_DRV_TIMER_INSTANCE(3);   // Internal timer[3]
nrf_drv_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
void init_my_timer()
{
    timer_cfg.frequency = NRF_TIMER_FREQ_16MHz; // Use the HF Clock
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrfx_timer_init(&m_timer3, &timer_cfg, timer3_event_handler);
    APP_ERROR_CHECK(err_code);

	nrfx_timer_extended_compare(&m_timer3,
							   NRF_TIMER_CC_CHANNEL0,
							   nrf_drv_timer_us_to_ticks(&m_timer3, 50) // Init 50uS timer NOTE: This is off by about 2uS
							   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
							   true);

}

==============================================================================
// Note I can use buttons to start/stop this timer on the nRF52 SD
    nrfx_timer_enable(&m_timer3);   // Start the timer
    nrfx_timer_disable(&m_timer3);  // Stop the timer
	
==============================================================================
//  Timer IRQ handler
static bool timer3_trig_state = false;
static void timer3_event_handler(nrf_timer_event_t event_type, void * p_context)
{
	// Toggle PO.13 (D2) every 50uS
	if (timer3_trig_state){
		*gpio_outclr_cfg = 1UL<<ARDUINO_2_PIN;
		timer3_trig_state = false;
	} else {
		*gpio_outset_cfg = 1UL<<ARDUINO_2_PIN;
		timer3_trig_state = true;
	}
}
	

Parents Reply Children
  • Hi Vidar.

    Thankyou for your feedback, it has been very helpful.

    I am seeing very low jitter in the PWM which is less than 0.1%.

    This is good enough for us.

    BUT I need to use a timer to trigger the PWM at 100Hz

    This timer seems to have a 2% jitter on a 2MHz clock taken when the external clock is running.

    I have raised the ISR priority to 2 and it seem better (<2% jitter).

    I'm not sure if there is any other way to do that.

    Adrian.

  • Hi Adrian,

    I'm glad to hear that it accuracy has improved.

    anealca said:

    BUT I need to use a timer to trigger the PWM at 100Hz

    This timer seems to have a 2% jitter on a 2MHz clock taken when the external clock is running.

    Please correct me if I'm wrong, but I assumed you wanted this to be a continuous clock signal. If you want to start the PWM every "1/100hz" seconds to play a shorter sequence, then I would recommend you connect the timer to the PWM with PPI. The problem with using the timer interrupt to trigger the PWM task is that it will take the program several CPU cycles to enter the interrupt handler.

    Attached below is an example put together to test the accuracy here, and it seems to be OK. Please try to run this on your board to see if you  get the same result.

    Test code based on the ble_app_hrs example
    nRF5_SDK17.1.0_ble_app_hrs_pwm_test.zip

    The waveforms I captured with my logic analyzer

    Vidar

Related