Excessively long boot time

Hi,

I was measuring the time it takes to boot to my application based on the nRF52832 and the time I measured was excessively long.

I'm using a PicoScope DSO for observing:

Channel B : P0.19 (LED3).

Channel C: P0.13 (BTN1).

Operation is simple:

1) I initialise P0.19 for output in PRE_KERNEL_1 and set it to 0, which turns the LED on.

2) In main(), just when my application code gets the control, I set P0.19 to 1, which turns the LED off.

3) I configure P0.13 for input and as a source for wake from power off.

4) Go to power off.

The idea is to go to power off, wake up on BTN1 press, and measure how long it takes to wake up, initialise, check the state of an input, then go to sleep again. The source code is at the end of this post.

First measurement: I measure the time elapsed from a hi-to-lo transition in P0.13 (button press) to a high-to-lo transition in P0.19 (write to LED output). It takes more than 300us!!! I need to make some H/W initialisation and checks very quickly after boot and PRE_KERNEL_1 looked like a good place to do it for me.

Second measurement: I measure the time elapsed from a hi-to-lo transition in P0.19 (LED on, enter to PRE_KERNEL_1)  to a lo-to-hi transition (enter into main function). It takes more than 380 ms!!!

The second pulse in P0.13 is, I guess, due to a switch bounce or temporary contact failure.

I'm using nRF Connect SDK version 1.9.1 and an nRF52 Development kit.

What can be causing these so long delays?

BR

Test Application Code:

#include <zephyr.h>
#include <sys/printk.h>
#include <stdio.h>
#include <init.h>
#include <nrfx_gpiote.h>
#include <pm/pm.h>
#include <pm/device.h>

#define BUSY_WAIT_S 2U
#define SLEEP_S 2U
#define CONSOLE_LABEL DT_LABEL(DT_CHOSEN(zephyr_console))

// Initialise to low a LED gpio. This goes to channel B of PicoScope.
static int configure_io(const struct device *dev)
{
	nrf_gpio_pin_write(DT_GPIO_PIN(DT_NODELABEL(led2), gpios), 0);
	nrf_gpio_cfg_output(DT_GPIO_PIN(DT_NODELABEL(led2), gpios));

	return 0;
}

SYS_INIT(configure_io, PRE_KERNEL_1, 0);

// static int disable_ds_1(const struct device *dev)
// {
// 	ARG_UNUSED(dev);

// 	pm_constraint_set(PM_STATE_SOFT_OFF);
// 	return 0;
// }

//SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0);

void main(void)
{
	nrf_gpio_pin_write(DT_GPIO_PIN(DT_NODELABEL(led2), gpios), 1);
	printk("Hello World! %s\n", CONFIG_BOARD);

	nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button0), gpios), NRF_GPIO_PIN_PULLUP);
	nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button0), gpios), NRF_GPIO_PIN_SENSE_LOW);

	printk("Entering system off; press BUTTON1 to restart\n");

	pm_power_state_force(0u, (struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});

	k_sleep(K_SECONDS(2));

	printk("ERROR: System off failed\n");

	while (true)
	{
	}
}

  • I'll share what I've found about this.

    System OFF is, to my opinion, appropriated for applications like a mouse or a keyboard, where a 300ms boot time poses little to no inconvenient for the first move or keystroke, but not for other applications, like mine.

    It takes so long to boot due to the time required for initialising everything and for starting the 32KHz crystal oscillator. It is possible to obtain better boot times using the internal RC oscillator, still not good for my application.

    The alternative is to use System ON low power mode, shutting down all non required peripherals. Using zephyr, this is mode is entered automatically when all tasks are put to sleep. This option is working for me, yet current consumption is a bit higher.

    BR

  • Hi,

    As you note, system OFF is a special low power mode that is only suitable for some applications in some specific cases.  With system on low power mode you also get a sleep current town to a few micro amps when you disable all peripherals you don't need. Wakeup from system on is fast, and there is no reset involved.

    A wakeup from system OFF on the other hand always involves a reset, and this means reconfiguring the IC from scratch. It also involves starting the 32.768 kHz oscillator again, which takes a long time if you use the (optional) 32.768 kHz crystal (instead of LFRC). This has a typical startup time of 250 ms, but it can also be longer. I expect this constitutes the vast majority of the startup time you are seeing (you can check this by testing with CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y to see if is reduced).

  • Thanks Einar for mentioning CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC.

    BR

Related