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

nRF52 clock in and out

I have two related questions about nRF52 (nrf52832) which I have not been able to pinpoint from the documentation.

  1. Can the 32MHz crystal connection be replaced by a 32MHz input if there is an existing clock in the system that meets the precision, tolerance, etc? On many processors, one of the two crystal pins may be used as an input while the other is left open if there is a driven external source, but I see no information about this for nRF52.

  2. What is the most power-efficient way to get a high frequency clock output from the nRF52? Other ARM processors seem to offer direct "HFCLK" outputs to pins, but I can't find any related features in the nRF52 documentation. The best I've been able to guess is that the SPIM or PWM blocks could be used to provide a clock (8MHz or 16MHz respectively?) but each of those draws additional power and we don't (in this case) need the remaining functionality of the peripherals.

Thank you.

  • The answer to question # 1 is no, it is not supported. It was possible on the nRF51, but the clock module is redesigned and external 32MHz clocks is not a feature of nRF52. You can try at your own discretion, but the new design is so sensitive to jitter and noise that Nordic will not make any guarantees. A crystal is needed to ensure performance.

  • Hello,

    I am also interested in outputting a 4MHz clock from nRF52 (actually I am using nRF52832). I have a few comments question on the code that you have supplied:

    1. Concerning this piece of code: 
      nrf_gpio_range_cfg_output(18); //Configure pin 18 as output
      I am using nRF5_SDK_14.2.0_17b948a, and there seems that the nrf_gpio_range_cfg_output function takes 2 arguments (both ends of the range), so you need nrf_gpio_cfg_output driver function instead.
    2. Concerning this piece of code:
      NRF_CLOCK->TASKS_HFCLKSTART = 1; //Start high frequency clock
      while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {
          //Wait for HFCLK to start
      }
      NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; //Clear event
      I think it would be cleaner to use the driver functions for code futureproofness/portability, would the following make it:
        if(!nrf_drv_clock_init_check())
          {
            err_code = nrf_drv_clock_init();
            APP_ERROR_CHECK(err_code);
          }
      
    3. Same comment for the PPI configuration, wouldn't it be cleaner if we used some driver call for this piece of code 
      //Configure PPI
      NRF_PPI->CH[0].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[0];
      NRF_PPI->CH[0].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[0];

      NRF_PPI->CHENSET = PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;
      like this:
          void my_clock_start_handler(nrf_drv_clock_evt_type_t event)
          {
            if(event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED)
              NRF_TIMER1->TASKS_START = 1;
            else
              APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
          }
          
          nrf_drv_clock_handler_item_t my_clock_handler_item_s = {
            .p_next = NULL,
            .event_handler = &my_clock_start_handler
          };
          
          void my_clock_start(void)
          {
          
            nrf_drv_ppi_init();
            err_code = nrf_drv_ppi_channel_alloc	(&my_4MHz_clck_ppi_channel_s);
            APP_ERROR_CHECK(err_code);
            
            err_code = nrf_drv_ppi_channel_assign	(my_4MHz_clck_ppi_channel_s,
           					 (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[0],
           					 (uint32_t) &NRF_GPIOTE->TASKS_OUT[0] );	  
            APP_ERROR_CHECK(err_code);
          
            err_code = nrf_drv_ppi_channel_enable(my_4MHz_clck_ppi_channel_s);
            APP_ERROR_CHECK(err_code);
          
            nrf_drv_clock_hfclk_request(&my_clock_handler_item_s);
          }
      
    4. Now, last but not least, I have one more question. I noticed that the code above does not work any longer after any call to NVIC_DisableIRQ(POWER_CLOCK_IRQn);
      For instance, when the SoftDevice is present, and the nrf_sdh_enable_request function from nrf-sdk/components/softdevice/common/nrf_sdh.c is called, then this function calls function sdh_state_observer_notify from the same file which in turn runs some state observers hooks, amongst which the sd_state_evt_handler from the nrf-sdk/components/drivers_nrf/clock/nrf_drv_clock.c file, which in turns calls NVIC_DisableIRQ(POWER_CLOCK_IRQn);.
      I would be quite greatfull to get some feedback why this happens…
  • Replying to myself.

    I just found why my code does not start the 4MHz code after the start of the BlueTooth. Because I was trying to write clean/futureproof code I used the nrf_drv_clock_hfclk_request function in order to make sure that the fast clock at 16MHz is running and stable before to start the timer.

    If instead of this I directly do the NRF_TIMER1->TASKS_START = 1; like in the original code, then the 4MHz clock is generated.

    So, my comment is that the way I start the BlueTooth does something wrong with the clock driver. Your help about this is welcome…

  • Hi Martin,

    I came across this question. I'm confused because in the docs for the Clock of the nRF52 here:

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fclock.html

    It seems to suggest you can use a 32 MHz clock with the nRF52 as a source for the HFXO. I've read the clock section of the docs a few time and still don't understand.

    If there's no external 32 MHz clock, what's the HFXO source? Internal?

    Why is it that all functionality can be done with no HF external clock, but a lot of other forum posts seem to suggest that you can't use Soft Device or BLE if you use an internal RC filter for the LFXO. Is that true? Is the 32.768 kHz external clock required for full nRF52 functionality?

    Thanks.

Related