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

Using app_timer to determine if boot loader should start

Background:

We have a product that has one button that both power it on and that is used for simple commands, there is also one led to indicate its status. The button is latching the power on so that the device is not consuming any power when it is shut down. This product was developed using the legacy bootloader of SDK11. In this bootloader we used the app_timer to measure how long the user pressed the button to determine if we should start BL or App. A long press followed by tapping it starts the BL. This was easy because the softdevice and ble_stack was initialized before the check was done. Now before production we are going to use the new secure bootloader, (will be flashed in production, devices with old bl will not be updated), in order to be compatible with future versions. We are going to start of with SDK 12.3 for now. 

In order to achieve this I have done some modifications to the secure bootloader and want to check with you that this is ok and will be a stable and good solution. We will also use the button-less dfu from app.

S132 v3.0.0. IAR 7.60.2 for the BL and IAR 8.30.1 for the App. The app uses FreeRTOS from SDK 14.2 and the rest is from SDK 12.3.

Secure BL Modifications:

The modifications are more or less copied from the legacy bootloader startup sequence:

  1. ble_stack_init(true) is moved from ble_dfu_transport_init() to nrf_dfu_init() (like the legacy bootloader only here it was in main.c). This is done right before nrf_dfu_enter_check.
  2. The initialization of the softdevice is commented out in nrf_bootloader_app_start. (because now the SD is already intialized)
  3. The softdevice_disable() is called before jumping to application (like the legacy bootloader).

ble_stack_init(true);

uint32_t nrf_dfu_init()
{
...
timers_init();
ble_stack_init(true);
scheduler_init();
//check time of button press and decide
.....
if(enter_bootloader_mode != 0 || !nrf_dfu_app_is_valid())
{
...
}
if (nrf_dfu_app_is_valid())
    {
        app_timer_stop_all();
        sd_softdevice_disable();
        NRF_LOG_INFO("Jumping to: 0x%08x\r\n", MAIN_APPLICATION_START_ADDR);
        nrf_bootloader_app_start(MAIN_APPLICATION_START_ADDR);
    }

Questions:

  • Is this ok? (it seems to work, but I need it to be bulletproof)
  • Are there any thing else I need to de-init before jumping to the app now that I have initialized the ble_stack and SD?
  • Are there any stability reasons for these design changes in the secure bl vs the legacy?
  • In the legacy bootloader the SD was not initialized if the app_reset was set. Do I need to do a similar check in the secure BL with my modification?

Finally I would suggest some minor design pattern changes to the bootloader. I really like the weak functions you have provided that gives the user an easy way of customizing the bl for his product, however for the LEDs this is not the case.We use various blinking patterns for our single LED and have to modify all the parts of the SDK-code where the LEDs are changed. In stead it would be nice if you provided weak functions for the state-changes in the BL that enabled the user to do what he/she wants with leds and other stuff. Also BSP_BUTTON3 has to be defined even though I only have one button. It is important to keep the custom code in one place, otherwise it will be very time consuming to upgrade to newer SDK versions.

Thanks in advance and best regards
Erik

Parents
  • Hello Erik,

    You mention that you use IAR 7.60.2 and IAR 8.30.1, so I just want to mention the release notes for our later SDKs regarding IAR versions. I don't think your are directly impacted by this, as your bootloader use IAR7, but it is worth keeping in mind for the future, in case you want to update the bootloader, and then use IAR8.

    Questions:

    Is this ok? (it seems to work, but I need it to be bulletproof)

    I don't see any issues with moving the ble_stack_init() to before the nrf_dfu_enter_check(), but is there a particular reason why you want to start it in the bootloader if the transport layer isn't used? Do you use the softdevice to decide whether or not to enter DFU or application? I see that the softdevice's vector table is set in nrf_bootloader_app_start(), but softdevice_enable() is not called by default.

    As long as you disable the softdevice before entering the app, I don't see a problem with it. I spoke to our SDK team, who has designed the bootloader, and he told me that there is no reason to change the nrf_bootloader_app_start() function, as long as you disable the softdevice before entering this. It doesn't actually start the softdevice, it only sets the vector tables. He actually also advised to clear the ICPR in addition to the ICER, like it is done in the bootloader from SDK15.2.0:

        // Disable and clear interrupts
        // Notice that this disables only 'external' interrupts (positive IRQn).
        NRF_LOG_DEBUG("Disabling interrupts. NVIC->ICER[0]: 0x%x", NVIC->ICER[0]);
    
        NVIC->ICER[0]=0xFFFFFFFF;
        NVIC->ICPR[0]=0xFFFFFFFF;
    #if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
        NVIC->ICER[1]=0xFFFFFFFF;
        NVIC->ICPR[1]=0xFFFFFFFF;
    #endif

     

    Are there any thing else I need to de-init before jumping to the app now that I have initialized the ble_stack and SD?

    If you enable the softdevice, you have to disable before entering the application. It is also a good idea to disable any other hardware peripherals, such as timers, that you may have started in the bootloader, or else they will keep running, drawing power.

     

    Are there any stability reasons for these design changes in the secure bl vs the legacy?

     The bootloader has become easier to understand in the later SDKs, so it is easier to work with, in my opinion at least. As mentioned earlier, the latest bootloader clears the ICPR, which is an improvement, to prevent any old interrupts to fire right after you start the application. So I guess there are some improvements. In addition to these, softdevice changes are the main reason for updating the bootloader in the later SDKs (as well as in the other examples). 

    In the legacy bootloader the SD was not initialized if the app_reset was set. Do I need to do a similar check in the secure BL with my modification?

    I guess that the reason for this is that there is no need to start the softdevice if it isn't used in the bootloader. It takes a bit of time, and hence, a bit of power to do this. If the chip resets without the intention of doing a DFU, there is no reason to start the SoftDevice in the bootloader.

    I hope this answered some of your questions. Let me know if anything is unclear, or if you have other bootloader-related questions.

    Best regards,

    Edvin

  • Thank you so much, that made me more confident that the modifications are robust. I also added the clearing of the ICPR.

    Yes, I am aware of the newer SDKs and would love to upgrade to those, but I am not sure if the product-owner wants to pay for those developing hours so we stay at a minimum of SDK12 for now.

    The reason I start the SD is that I didn't get the app_timer to run/count without it. I guess the RTC interrupts need the SD to be enabled to propagate them to the app_timer or something?

    Hmm, I tried to add the nrf_dfu_mbr_init_sd() back in to nrf_bootloader_app_start() again, but it fails if it is already called, which it now is. So I'll leave it commented out.


    BR Erik 

  • Erik said:
    Hmm, I tried to add the nrf_dfu_mbr_init_sd() back in to nrf_bootloader_app_start() again, but it fails if it is already called, which it now is. So I'll leave it commented out.

     Yes. Sorry. That is correct. Leave that commented out.

    Erik said:

    The reason I start the SD is that I didn't get the app_timer to run/count without it. I guess the RTC interrupts need the SD to be enabled to propagate them to the app_timer or something?

     It should be possible to use without the SoftDevice. However, if your application works now, I assume it is fine, but look into the nrf_drv_clock_init() function. It behaves a bit differently when the softdevice is enabled and when it isn't, depending on whether SOFTDEVICE_PRESENT is defined in your preprocessor defines or not. 

    Regarding the button3, I see your point. It is difficult to make it work "out of the box" on a DK, and at the same time be completely modifiable from one file. But I agree that the button 3 3 handling could be done in a different way. 

    One way is of course to modify your custom_board.h file, and define the BOOTLOADER_BUTTON from there, which will lead to a redefinition, but it could work as a reminder to remove the default define when porting to new SDKs.

    BR,

    Edvin

Reply
  • Erik said:
    Hmm, I tried to add the nrf_dfu_mbr_init_sd() back in to nrf_bootloader_app_start() again, but it fails if it is already called, which it now is. So I'll leave it commented out.

     Yes. Sorry. That is correct. Leave that commented out.

    Erik said:

    The reason I start the SD is that I didn't get the app_timer to run/count without it. I guess the RTC interrupts need the SD to be enabled to propagate them to the app_timer or something?

     It should be possible to use without the SoftDevice. However, if your application works now, I assume it is fine, but look into the nrf_drv_clock_init() function. It behaves a bit differently when the softdevice is enabled and when it isn't, depending on whether SOFTDEVICE_PRESENT is defined in your preprocessor defines or not. 

    Regarding the button3, I see your point. It is difficult to make it work "out of the box" on a DK, and at the same time be completely modifiable from one file. But I agree that the button 3 3 handling could be done in a different way. 

    One way is of course to modify your custom_board.h file, and define the BOOTLOADER_BUTTON from there, which will lead to a redefinition, but it could work as a reminder to remove the default define when porting to new SDKs.

    BR,

    Edvin

Children
No Data
Related