Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GPIO reset when Booloader starts Application

I'm developing a project where the device wakes from system_off using a button.  I've noticed that it takes about half a second from the time the bootloader starts until the application loads.  I tested this by turning on an LED at the beginning of the bootloader's main(), turning it off just before the call to nrf_bootloader_app_start() in nrf_dfu.c, and then turning it back on once again at the beginning of the Application's main().  I also turn on a second LED at the beginning of the bootloader, and leave it on.

The bootloader takes about 250ms to get up to nrf_bootloader_app_start().  And then it takes another 300ms to get to the beginning of the Application main().  During the 300ms, the second LED (the one I leave on) turns off.

That leaves me with two questions:

1)  What is happening during that 300ms that is taking so long?
2)  Something is resetting the GPIO configuration when the bootloader starts the application.  What is it, and can it be disabled?

For reference, I'm using SDK 13.0.0 on an nRF52832 with softdevice s132.

Parents
  • Hi,

    1) Have you modified the bootloader so that it ramps up the HF/LF crystal during startup? Typical startup time for a LF crystal is 250 ms (clock spec.), which could explain the delay you are seeing.  I measured the same to ~13 ms with the default bootloader from SDK 13.0.0

    2) The bootloader does not reset the GPIO module when booting the application, but the app will typically re-initialize the IOs during startup. Do you see the same if you don't initialize GPIO pins in your app?

  • I have not modified the bootloader, but the hardware includes a 32kHz crystal.  In the sdk_config.h for the bootloader, I have this:

    #define CLOCK_ENABLED 0

    In the application, I have this:

    #ifndef CLOCK_ENABLED
    #define CLOCK_ENABLED 1
    #endif
    #if CLOCK_ENABLED
    ...
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth
    #ifndef CLOCK_CONFIG_LF_SRC
    #define CLOCK_CONFIG_LF_SRC 1
    #endif

    This leads me to believe that you're correct--it's the ramp-up time of the LF crystal.  Also in the application, initializing the LEDs and turning one of them on is literally the first thing in main():

    int main(void)
    {
    	configLedPin(LED_PIN_RED);
    	configLedPin(LED_PIN_BLU);
    	configLedPin(LED_PIN_GRN);
    	NRF_P0->OUTCLR = (1<<LED_PIN_GRN);
    

    Is there an easy way to turn on the LED before the LF clock is ramped up?  From what I can see, the call stack is something like this:

    nrf_clock_lf_src_set
    called by nrf_drv_clock_init
    called by nrf_drv_clock_on_sd_enable
    called by softdevice_handler_init
    called by ble_stack_init (within Application)

    In my application, however, ble_stack_init isn't called until well after main() initializes a bunch of other stuff (gpio, saadc, TWI, UART, app_timer, etc).

  • There are three things that can request ramp up of the LF crystal: call to nrf_drv_clock_lfclk_request() after clock_init(), writing '1' to NRF_CLOCK->TASKS_LFCLKSTART, or call to ble_stack_init()/sd_softdevice_enable(). So it looks like you are turning off the LED before LF start task is triggered. Also,  the bootloader should not start the LF clock unless it enters DFU mode (BLE transport will start the crystal)

    Maybe you can try with the RCOSC instead to check if this is indeed caused ramp up time of the LF crystal. Startup time for RCOSC is 600 us for comparison.

    Code changes to use internal RC as LF clock source:

    /*In sdk_config*/
    
    // <o> CLOCK_CONFIG_LF_SRC  - LF Clock Source
     
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth 
    
    #ifndef CLOCK_CONFIG_LF_SRC
    #define CLOCK_CONFIG_LF_SRC 0
    #endif
    
    /*in ble_stack_init()*/
    
    nrf_clock_lf_cfg_t clock_lf_cfg = {.source = NRF_CLOCK_LF_SRC_RC,
                                       .rc_ctiv = 16,
                                       .rc_temp_ctiv = 2};

        

     

  • Driving the pin low is what turns on the LED--sorry I wasn't clear on that before.  To clarify:

    1) The bootloader turns on the LED
    2) 250-ish ms later, something turns off the LED (very soon after calling nrf_bootloader_app_start())
    3) 300 ms after the LED turns off, it gets turned on by the Application's main(), in the supplied code snippet

    So it looks like something is resetting the gpio configuration, and then something else is requesting a ramp up of the LF crystal, before the Application's main() is called.  I notice that nrf_bootloader_app_start calls nrf_dfu_mbr_init_sd() - would that be the culprit?

  • Are you sure there is nothing else in the app that reconfigure the IOs after startup? I removed all io configurations from the bootloader code, then configured the LED_4 pin to indicate startup of bootloader and app.  I have not managed to reproduce the delays. IO states from bootloader are also kept when entering the main app. 

    /*bootloader main()*/
    
    int main(void)
    {
        nrf_gpio_cfg_output(LED_4);
        nrf_gpio_pin_set(LED_4);
        ...
        
    /*App main - used blinky_pca10040_s132 as starting point*/
    
    int main(void)
    {
        /*Already configured to output by bootloader*/
        nrf_gpio_pin_clear(LED_4);
        
        /*Configure wake-up pin*/
        nrf_gpio_cfg_sense_input(BUTTON_1,
                                 NRF_GPIO_PIN_PULLUP,
                                 NRF_GPIO_PIN_SENSE_LOW); 
    
        /* Toggle LEDs. */
        while (true)
        {
            
            nrf_delay_ms(5000);
            NRF_POWER->SYSTEMOFF = 1;
            
        }
    }

    LED_4 pin timing captured with logic analyzer:

    nrf_dfu_mbr_init_sd() tells the MBR to start forwarding interrupts to the softdevice, but it will not start any clock sources.

     

Reply
  • Are you sure there is nothing else in the app that reconfigure the IOs after startup? I removed all io configurations from the bootloader code, then configured the LED_4 pin to indicate startup of bootloader and app.  I have not managed to reproduce the delays. IO states from bootloader are also kept when entering the main app. 

    /*bootloader main()*/
    
    int main(void)
    {
        nrf_gpio_cfg_output(LED_4);
        nrf_gpio_pin_set(LED_4);
        ...
        
    /*App main - used blinky_pca10040_s132 as starting point*/
    
    int main(void)
    {
        /*Already configured to output by bootloader*/
        nrf_gpio_pin_clear(LED_4);
        
        /*Configure wake-up pin*/
        nrf_gpio_cfg_sense_input(BUTTON_1,
                                 NRF_GPIO_PIN_PULLUP,
                                 NRF_GPIO_PIN_SENSE_LOW); 
    
        /* Toggle LEDs. */
        while (true)
        {
            
            nrf_delay_ms(5000);
            NRF_POWER->SYSTEMOFF = 1;
            
        }
    }

    LED_4 pin timing captured with logic analyzer:

    nrf_dfu_mbr_init_sd() tells the MBR to start forwarding interrupts to the softdevice, but it will not start any clock sources.

     

Children
No Data
Related