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

configuring gpio pin stops LFXO and RTC counter

I found that blindly configuring all GPIO pins can stop the LFXO and RTC counter. I am reporting this as: something to be aware of, not obvious to everyone. Not a question, just saying "don't do that, or do it in a different order."

After starting the LFXO clock and enabling RTC counter I did this:

for (uint32_t pin = 0; pin < 32; pin++) {

	// Configure high current output (max 5mA)
	nrf_gpio_cfg(
			pin,
			NRF_GPIO_PIN_DIR_INPUT,
			NRF_GPIO_PIN_INPUT_DISCONNECT,
			NRF_GPIO_PIN_PULLDOWN,
			NRF_GPIO_PIN_H0H1,	// !!! high current
			NRF_GPIO_PIN_NOSENSE);
}

This code changes the pin configurations to have a pulldown and high current, different from their reset condition (but still not connected, same as reset.) Just looking at Figure 1 under GPIO in the product spec, it is not clear to me why this stops the RTC counter. I understand that the physical pin is shared between the LFXO crystal and the GPIO port. I guess that the ANAEN signal is controlled by the LF clock and that somehow configuring the GPIO pin disrupts that.

  • Yes, maybe it is only the LFXO. A wild supposition: they implemented a ring oscillator using the GPIO buffers to save silicon?

  • You are right butch, we should test it. But I couldn't reproduce the issue here. Here is my code, I modified the rtc example in the SDK:

    int main(void)
    {
    
    
        lfclk_config();
        leds_config();
        rtc_config();
        NRF_CLOCK->LFCLKSRC =1 ;
        for (uint32_t pin = 0; pin < 32; pin++) {
        // Configure high current output (max 5mA)
        nrf_gpio_cfg(
                pin,
                NRF_GPIO_PIN_DIR_INPUT,
                NRF_GPIO_PIN_INPUT_DISCONNECT,
                NRF_GPIO_PIN_PULLDOWN,
                NRF_GPIO_PIN_H0H1,  // !!! high current
                NRF_GPIO_PIN_NOSENSE);
        }
        nrf_gpio_cfg_output(21); //(for the LED)
        while (true)
        {
            __SEV();
            __WFE();
            __WFE();
        }
    }
    

    Can still see the LED blinking.

  • OK, thanks. Now I should try and reproduce the problem. But why do you call "NRF_CLOCK->LFCLKSRC =1 ;" inside the loop? In other words, maybe that masks the problem, isn't that reconfiguring the LF clock to be LFXO AFTER you have configured the GPIO pin? Please try it without that line in the loop. (The reason I didn't send you a small test case is that I discovered the alleged problem inside a complex app, I am not equipped to build small test cases every day. Again, thanks for your attention. I hope I have not wasted your time.)

  • Sorry, I should have had put it outside. I updated, the result was the same.

  • I tried to replicate. My code is below. When I step into the code on the debugger, it doesn't complete (infinite loop at the last waitOneTick()) meaning the RTC0 counter has stopped. If I don't step, but just resume the debugger, main() does complete. I don't understand why it behaves differently depending on whether I am single-stepping. The RTC and clocks should still be running while debugging. My environment is Eclipse/GCC ARM/C++.

    /*
     * Test whether configuring GPIO pins stops LFXO and RTC0 counter.
     * As alleged in Nordic Devzone thread.
     */
    
    #include "nrf_clock.h"
    #include "nrf_rtc.h"
    #include "nrf_gpio.h"
    
    
    
    unsigned int ticks(){
    	return nrf_rtc_counter_get(NRF_RTC0);
    }
    
    // spin until RTC0 counter increments at least once
    void waitOneTick(){
    	unsigned int firstTime, nextTime;
    
    	firstTime = ticks();
    	do {
    		nextTime = ticks();
    	}
    	while (nextTime == firstTime);
    }
    
    void configureAllGpioPins() {
    	for (uint32_t pin = 0; pin < 32; pin++) {
    
    		/*
    		 * This configuration is same as POR state except:
    		 * 1. high current output (max 5mA) instead of normal
    		 * 2. pulldown instead of no pull
    		 */
    		nrf_gpio_cfg(
    				pin,
    				NRF_GPIO_PIN_DIR_INPUT,
    				NRF_GPIO_PIN_INPUT_DISCONNECT,
    				NRF_GPIO_PIN_PULLDOWN,	// !!! pulldown
    				NRF_GPIO_PIN_H0H1,	// !!! high current
    				NRF_GPIO_PIN_NOSENSE);
    	}
    }
    
    int main(void)
    {
    	// configure lf clock source is xtal
    	nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_Xtal);
    
    	// start lf clock
    	nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
    
    	// spin until LFXO is stable
    	while (! nrf_clock_lf_is_running()) {}
    
    	// RTC0 begin counting (ticks always from LF clock)
    	nrf_rtc_task_trigger(NRF_RTC0, NRF_RTC_TASK_START);
    
    	waitOneTick();
    
    	/*
    	 * configure all gpio pins
    	 * Despite some pins already used by LFXO xtal
    	 */
    	configureAllGpioPins();
    
    	waitOneTick();
    }
    
Related