MCUBoot DFU OTA Best way to obtain actions ( Hooks ) also Android vs iOS discrepancies.

Hi There, 

Environment Description: 

 1. nRF Connect for VS Code v2023.1.44.

 1.  NCS Version v2.0.0. 

 2. Zephyr v3.0.99-ncs1.

 3. MCUBoot v1.9.99

 4. NRF52840.

 5. NRF Connect mobile app Android v 4.26.0 Mobile app IOS V 2.6.

I am currently working on the implementation of OTA DFU using BLE, I have successfully implemented this functionality after following the documentation here., However there are some questions and perhaps missing functionality to fulfill our product's requirements, taking into account that our product consists of an LCD which should display the state of the update as it goes along. 

By using these image management callbacks I am able to get the start of the DFU process as well as the DFU Pending event, nonetheless there is a discrepancy depending on which kind of device is used to perform for instance:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void dfuStartedCb(void){ LOG_ERR("STARTTING DFU"); }
static void dfuStoppedCb(void){ LOG_ERR("STOPPED DFU"); }
static void dfuPendingCb(void){ LOG_ERR("PENDING DFU"); }
static void dfuConfirmedCb(void){ LOG_ERR("CONFIRMED DFU"); }
const struct img_mgmt_dfu_callbacks_t dfu_callbacks = {
.dfu_started_cb = dfuStartedCb,
.dfu_stopped_cb = dfuStoppedCb,
.dfu_pending_cb = dfuPendingCb,
.dfu_confirmed_cb = dfuConfirmedCb,
};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

From an Android the workflow is as follows: 

1. DFU Started form mobile phone -> 2. Get DFU Started Callback. -> 3. ~ 30 Seconds transferring the image. -> 4. Device goes into MCUBoot .... -> 5. ~30-40 Seconds later, Device resets. -> 6. get the Image confirmed callback.

  

Question 1: Why does step 5 take that long ? ( After Jumping to the first Image slot ).

2. From an iPhone However the workflow changes slightly as the confirmed callback is never received by the application, Which makes it tricky to display user updates: 

Question 2: Why does the update from iPhone does generate the Confirmed callback ?

Question 3: Why are the swap types different (Android -> "Swap type: test", iPhone -> "Swap type: perm") ?

Finally, I would very much appreciate advise in regards to obtaining MCUBoot status actions in order to update the LCD accordingly while the bootloader is doing its magic, I did have a look online and found a couple of references to CONFIG_MCUBOOT_ACTION_HOOKS here, unfortunately it seems to be undefined when included in my child_image/mcuboot.conf file. 

Question 3: What is the best way to obtain MCUBoot actions to execute my own code ( is there a sample for this ) ? 

MCUBoot Configuration: 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#################################### Power Management ##########################################
CONFIG_PM=n
CONFIG_MAIN_STACK_SIZE=20480
CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h"
####################################### Boot Signature ##########################################
CONFIG_BOOT_ENCRYPT_RSA=n
CONFIG_BOOT_ENCRYPT_EC256=n
CONFIG_BOOT_ENCRYPT_X25519=n
CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN=3072
CONFIG_BOOT_SIGNATURE_KEY_FILE="ngp_sign_rsa-3072.pem"
################################### Boot Configurations ##########################################
CONFIG_BOOT_UPGRADE_ONLY=n
CONFIG_BOOT_BOOTSTRAP=n
CONFIG_BOOT_VALIDATE_SLOT0=y
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Main project Configuration: 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192
#################################### BLE Configuration #################################
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=n
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="NGP-BL"
#BLE Allow connection parameters update.
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=y
# BLE connection interval suggestion.
CONFIG_BT_PERIPHERAL_PREF_MAX_INT=20
CONFIG_BT_PERIPHERAL_PREF_MIN_INT=20
#BLE Buffering configuration.
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_ATT_PREPARE_COUNT=20
CONFIG_BT_BUF_ACL_TX_COUNT=20
CONFIG_BT_BUF_ACL_RX_COUNT=20
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Cheers !

Parents
  • Hi Felipe, 


    I will need help from our Mobile app team to answer most of your questions and get back to you. 

    I can try to answer question 1 though.

    At step 5 I would assume it's when the MCUBoot start the swapping process. The process involve erasing page by page of both Primary Slot and Secondary Slot and copy the image page by page from one slot to another slot. 
    This actually can take a lot of time considering erasing one page would require up to 90ms. And this is not include the calculation time needed to verify the hash of the image. The larger the image the longer it takes. 

    In the last question I assume you mean "your own code" not "won code" ?

  • Hi Hung, 

    Thanks for your prompt response. 

    Awesome, So we should then wait for the mobile team to get back to us in regards to question 2 and 3. 

    In regards to the last question (Apologies for the typo) , since the answer in question 1 is that it may take reasonably long to perform these actions, I would want to be able to somehow ( Since at that instance the device will appear unresponsive to the user ) notify the user that the operation is happening i.e ( LCD Display  or a GPIO toggle etc. ) is this possible ? 


    Cheers,  

    Thanks

Reply
  • Hi Hung, 

    Thanks for your prompt response. 

    Awesome, So we should then wait for the mobile team to get back to us in regards to question 2 and 3. 

    In regards to the last question (Apologies for the typo) , since the answer in question 1 is that it may take reasonably long to perform these actions, I would want to be able to somehow ( Since at that instance the device will appear unresponsive to the user ) notify the user that the operation is happening i.e ( LCD Display  or a GPIO toggle etc. ) is this possible ? 


    Cheers,  

    Thanks

Children
  • Hi Felipe, 
    I haven't implemented the hooks myself but what I can see from the code is that you would need to add your own function named  mcuboot_status_change() into mcuboot. 
    If you look into \bootloader\mcuboot\boot\zephyr\main.c you can find that it will call mcuboot_status_change() on each stage of the mcuboot process: 

    As far as I know this function should be implemented in mcuboot, not in your application because your application will not run when the Mcuboot is doing its job. 

  • Hi Hung, 

    I had a look at ncs/v2.0.0/bootloader/mcuboot/boot/zephyr/main.c and I find no references to mcuboot_status_change() also line numbers do not match as shown below, we must be looking ad different versions of ncs. 

    Also, Is there any way this might be achieved without having to modify the bootloader ? otherwise the whole idea of mcuboot hooks is lost. 

    What is Nordic's recommended way of achieving this indications from the bootloader ? 

    Cheers, 

  • Hi Felipe, 
    As far as I know mcuboot_status_change() and CONFIG_MCUBOOT_ACTION_HOOKS was only added from NCS v2.1.0 .

    You may want to consider upgrading to newer SDK.  

    I understand that you don't want to modify the bootloader. I'm checking internally if we have an example that doesn't need to do that. My understanding is that it should be possible to add the function in a file and then compile the mcuboot as childimage with the extra file. 

  • Hi again Felipe, 
    I got the suggestion from our colleague on how to do it (still you need to update to v2.1 or newer) 

    In CMakeLists.txt in boards/arm/your_board , you can add something like this:
    if(CONFIG_MCUBOOT)
    zephyr_library()
    zephyr_library_sources(my_mcuboot_hook.c)
    endif()
    Then place a my_mcuboot_hook.c, that has the mcuboot_status_change() function, in boards/arm/your_board

    By doing this you don't have to change mcuboot. 
  • Hi Hung, 

    I have migrated my application from ncs 2.0.0 to 2.2.0 in order to access the Mcuboot hooks functionality: 

    Steps followed: 

    1. In child_image/mcuboot.conf added: 

    Fullscreen
    1
    CONFIG_MCUBOOT_ACTION_HOOKS=y
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    2. Added a CMakeLists.txt file in boards/arm/my_board containing the following: 

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    if(CONFIG_MCUBOOT)
    zephyr_library()
    zephyr_library_sources(mcuboot_hook.c)
    endif()
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    3. in boards\arm\my_board added a mcuboot_hook.c file containing: 

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include "bootutil/image.h"
    #include "bootutil/fault_injection_hardening.h"
    #include "bootutil/boot_hooks.h"
    #include "bootutil/mcuboot_status.h"
    void mcuboot_status_change(mcuboot_status_type_t status){
    LOG_INF("mcuboot status: %d ", status);
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    NB:I had to include some extra files here in order to be able to compile it as there was some types missing. 

    Thank you very much for your help. 

    Is there a reason for these files to be under my_board directory ? 

    Could you please elaborate on what was done on step 2 above ? , I know it works but I would like to understand it better.

    Lastly, How could I include the mcuboot directory to my path so I can get rid off of these errors:

    Cheers,