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

Using PPI to enable/disable HFCLK

Is it possible to use PPI and RTC to turn the HFCLK on or off ? (external Xtal)

Example - something like this ... NRF_PPI->CH[9].EEP = (uint32_t) &NRF_RTC0->EVENTS_COMPARE[1]; NRF_PPI->CH[9].TEP = (uint32_t) &NRF_CLOCK->TASKS_HFCLKSTART; NRF_PPI->CHENSET = PPI_CHENSET_CH9_Msk;

NRF_PPI->CH[10].EEP = (uint32_t) &NRF_RTC0->EVENTS_COMPARE[2]; NRF_PPI->CH[10].TEP = (uint32_t) &NRF_CLOCK->TASKS_HFCLKSTOP; NRF_PPI->CHENSET = PPI_CHENSET_CH10_Msk;

Does the PPI system require the HFCLK External Xtal to be operational ?

Also, if I can't use PPI to do the above, is there another way to do it ? Perhaps using shortcuts ? As I understand, shortcuts are only for use within the same peripheral and so probably not.

  • Hi shyam

    Your assumption is correct, shortcuts are only to use within the same peripheral. With PPI, you can connect an event of one peripheral with a task of another peripheral.

    There should be no problem with using PPI to stop the 16MHz crystal. The PPI does not need the 16MHz crystal, it only needs 16MHz RC. The RTC uses either 32kHz RC or crystal.

    You can see peripheral resource dependency in table 33 in nRF51822_PS v3.1. The PPI is not listed in this table, but it uses 16MHz RC.

    Update 18.8.2015 I have attached a code below to show how this is possible

    rtc0_triggering_HFLCK_start_and_stop_via_ppi.zip

  • Hi Stephan

    I tried your suggestion. See below. This code doesn't work. It asserts in the end (last line).

    ==========

    ASSERT(((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) == (CLOCK_HFCLKSTAT_STATE_NotRunning << CLOCK_HFCLKSTAT_STATE_Pos) ) || \
                   ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_SRC_Msk) == (CLOCK_HFCLKSTAT_SRC_RC << CLOCK_HFCLKSTAT_SRC_Pos))); /* ensure clock is stopped */
    
    NRF_RTC0->INTENCLR = RTC_INTENCLR_COMPARE1_Msk;
    NRF_RTC0->EVTENCLR = RTC_EVTENCLR_COMPARE1_Msk;
    NRF_PPI->CH[9].EEP = (uint32_t) &NRF_RTC0->EVENTS_COMPARE[1];
    NRF_PPI->CH[9].TEP = (uint32_t) &NRF_CLOCK->TASKS_HFCLKSTART;
    NRF_PPI->CHENSET |= PPI_CHENSET_CH9_Msk;
    #define TEST_TICKS (3)
    #define TICKS_TO_US(ticks) ((uint64_t)ticks*(uint64_t)1000000/32768)
    NRF_RTC0->CC[1] = NRF_RTC0->COUNTER + TEST_TICKS;
    nrf_delay_us(TICKS_TO_US(TEST_TICKS)); /* wait until RTC fires TEST_TICKS */
    nrf_delay_us(TICKS_TO_US(TEST_TICKS)); /* a little extra wait to make sure */
    nrf_delay_ms(2); /* Wait 1 ms of warmup time and an extra 1 ms to make sure */
    ASSERT(((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) == (CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos) ) && \
                 ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_SRC_Msk) == (CLOCK_HFCLKSTAT_SRC_Xtal << CLOCK_HFCLKSTAT_SRC_Pos)));
    

    ===============

  • Stefan, I thought the SET and CLR (CHENSET) registers in peripherals are for avoiding doing the operation that you mentioned?

  • Yes, you are correct. Thank you for the correction. I have edited my answer to correct myself.

Related