How do I turn off the clock for RF? CLOCK_CONTROL_NRF_SUBSYS_HF

Hi,

On nRF52811 I use simple ESB radio for TX.  Before TX I turn Clock for radio on like in the example:

int clocks_start(void)
{
	int err;
	int res;
	struct onoff_manager *clk_mgr;
	struct onoff_client clk_cli;

	clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
	if (!clk_mgr) {
		return -ENXIO;
	}

	sys_notify_init_spinwait(&clk_cli.notify);

	err = onoff_request(clk_mgr, &clk_cli);
	if (err < 0) {
		return err;
	}

	do {
		err = sys_notify_fetch_result(&clk_cli.notify, &res);
		if (!err && res) {

			return res;
		}
	} while (err);

	return 0;
}

After TX is done, I want to turn this clock OFF. I assume at least that I have to do it - because after the TX I want to go to sleep mode with the lowest possible consumption. Now After TX is done, the CPU has nothing to do and the consumption is about 400 uA, when I do not turn the HF clock to ON the power consumption falls down about to 7 uA.

How to turn the clock off? Or something else I need to do?

P.S. Where I can find this kind of information? I am used to work with STM32 - Go to datasheet - find register and coresponding bit, then look in to HAL or LL lib and I am looking for the fuctions which works with this bit it - then I can easily find the function to be called. But in Nordic SDK I am lost.. How do you do that?

Thank you very much

  • Hello,

    Thank you for contacting DevZone at NordicSemi.

    To go to the Datasheet / Product Specification of any nordic SoC, please go to InfoCenter or the TechDocs.

    You will find detailed chapters on peripherals and their registers.

    We also provide HAL and Driver files for nordic peripherals. We have a collection of drivers and HAL called NRFX.

    You will find all these within the SDK and on the Github.

    As the Nordic's Connect SDK (NCS) is Zephyr RTOS based sdk, it is preferred to use Zephyr APIs and libraries.

    Also, we refer our customers to base their designs or start with the samples provided in the NCS (which contains both the Zephyr samples and Nordic specific samples).

    I am not sure how relevant to you it will be, but you can start by looking at ESB Transmitter sample, and then modify the code as per your requirements.

    Coming to the query which you have:
    As ESB is one of the supported protocols in the SDK, we has This ESB user guide that describes what it is and how to use with nordic devices.
    Within the product specification, we see that the clock system has "start" and "stop" tasks and have two corresponding events called "started" and "stopped".

    To start the HFClock, we need to set/enable the "start" task for HFClock and wait till it has been enabled.
    To stop the HFClock, we need to set/enable the "stop" task for HFClock and wait till it has been disabled.

    Showing sample code for starting HFClock:

    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);

    With regards,

    Naeem

  • Hi Naeem,

    Thank you for detailed answer!. Your code solved my problem. Anyway I would prefer to use Zephyr API as you wrote. I went to zephyr API and found this. Could it be he function what I am looking for to STOP HFLCK? 

    If yes, the input params *device  and sys - where I can get it? In nrf52840dk_nrf52811.dts I could not find nothing about clk.

    Maybe rather than a solution, I would be interested in how to proceed so that I can use the API myself next time.

  • Hello,

    Yes, you can use that API.

    From the 

    #include <zephyr/drivers/clock_control.h>
     we have 
    static int clock_control_on(const struct device *dev, clock_control_subsys_t sys);

    where the device is the clock-peripheral and the clock-control-subsystem is the HFCLock subsystem.

    (For details, please look at clock_control.h, nrf_clock_control.h, and clock_control_nrf.c).

    We can get the device and subsystem as:

    #define sys ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK)
    
    static const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(clock));
    

    /BR, Naeem

  • Thank you,

    I have tried but still can't succeed: I am exactly following the ESB TX example. All I need is to turn off the HFCLOCK after each transmission (believing that I reduce consumption to a minimum). I use Zephyr and my goal is to periodically transmit one packet every second. I have a SW timer that is triggered after each TX done and transmits again in a second, so I want Zephyr to put the processor to sleep as deeply as possible to reduce consumption between each transmission. I tried 2 ways:

    1. Using registers:
      NRF_CLOCK->TASKS_HFCLKSTOP = 1;
      while ((NRF_CLOCK->HFCLKSTAT & (1<<16)));
      But when I do this, HFCLKSTAT only changes the source from Xtall to RC, but STATE is still running, does that mean that the internal HFCLK RC is needed as a source for CPU operation and cannot be turned off, but is it turned off by zephyr upon entering sleep?

    2. I called while(clock_control_off(dev, CLOCK_CONTROL_NRF_SUBSYS_HF) !=0); But this loop gets stuck and never ends - the clock is still running on Xtall.

    3. If I disable the HCLK through the registers after TX_Done, it seems that Zephyr falls asleep and is no longer awakened by the software timer which is supposed to send the next packet. I don't understand this. However, if I connect via RTT to CPU what is happening in the processor, everything works fine. 


      Thank you.
Related