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:

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,

};

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: 

#################################### 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
CONFIG_BOOT_SWAP_SAVE_ENCTLV=n

##################################### Clock Configuration ########################################
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
# See DRGN-15979: at https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/known_issues.html
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y

######################################## Flash Configuration ######################################
CONFIG_FLASH=y
CONFIG_FPROTECT=y
CONFIG_DISABLE_FLASH_PATCH=y

######################################## Console Logs Configuration ################################
CONFIG_LOG=y
CONFIG_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_SERIAL=n
CONFIG_LOG_MODE_MINIMAL=y 
CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0

######################################### Optimizations ###########################################
CONFIG_SIZE_OPTIMIZATIONS=y

Main project Configuration: 

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
CONFIG_BT_L2CAP_TX_MTU=498
CONFIG_BT_BUF_ACL_RX_SIZE=502
CONFIG_BT_BUF_ACL_TX_SIZE=502
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251


# Bluetooth PHY selection.
CONFIG_BT_CTLR_PRIVACY=n
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_CTLR_PHY_2M=y


# BLE Configuration.
CONFIG_BT_DEVICE_NAME_DYNAMIC=y

##################################### Power Management #########################################

CONFIG_PM=y
# Required to disable default behavior of deep sleep on timeout
CONFIG_PM_DEVICE=y
CONFIG_REBOOT=y

#################################### Peripheral Configuration ###################################

CONFIG_GPIO=y
CONFIG_GPIO_AS_PINRESET=y
CONFIG_I2C=y

################################# Native peripheral configuration ###############################

CONFIG_NRFX_PPI=y
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_TIMER1=y
CONFIG_NRFX_SAADC=y

# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y

############################### Multiprotocol service layer. #################################### 

CONFIG_MPSL=y

########################################## Utilities ###########################################
# Allow use of sprintf and print
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

####################################### FOTA Configuration #####################################

# Device firmware update (DFU) configuation
CONFIG_MCUMGR=y

# Bootloader configuration
CONFIG_BOOTLOADER_MCUBOOT=y # Ensure an MCUboot-compatible binary is generated

# Enable the Bluetooth mcumgr transport (unauthenticated).
CONFIG_MCUMGR_SMP_BT=y
CONFIG_MCUMGR_SMP_BT_AUTHEN=n
CONFIG_MCUMGR_SMP_BT_CONN_PARAM_CONTROL=y

# Enable the mcumgr Packet Reassembly feature over Bluetooth and its configuration dependencies.
# MCUmgr buffer size is optimized to fit one SMP packet divided into five Bluetooth Write Commands,
# transmitted with the maximum possible MTU value: 498 bytes.
CONFIG_MCUMGR_SMP_REASSEMBLY_BT=y
CONFIG_MCUMGR_BUF_SIZE=2475
CONFIG_OS_MGMT_MCUMGR_PARAMS=y

# Required by the `taskstat` command.
CONFIG_THREAD_MONITOR=y

# Support for taskstat command
CONFIG_OS_MGMT_TASKSTAT=y

# Enable statistics and statistic names.
CONFIG_STATS=y
CONFIG_STATS_NAMES=y
# LOG Level for MCUBoot
CONFIG_MCUBOOT_UTIL_LOG_LEVEL_DBG=y

# Required for rebooting
CONFIG_MCUMGR_CMD_OS_MGMT=y 
CONFIG_MCUMGR_CMD_IMG_MGMT=y


CONFIG_MCUBOOT_IMG_MANAGER=y

######################################## Console Logs Configuration ################################

# Enable console 
CONFIG_CONSOLE=y
# Enable RTT logging.
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

# Logging subsystem configuration
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
# Use this mode for time sensitive logging
# CONFIG_LOG_MODE_DEFERRED=y
# CONFIG_LOG_BUFFER_SIZE=2048 
CONFIG_LOG_BACKEND_SHOW_COLOR=y
CONFIG_LOG_INFO_COLOR_GREEN=y

# Disable Logs from I2C driver, may turnback on for debugging. 
CONFIG_I2C_LOG_LEVEL_OFF=y

################################### Clock Configuration ########################################

CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
# See DRGN-15979: at https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/known_issues.html
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y

################################### Dynamic Memory Allocation ##################################

CONFIG_HEAP_MEM_POOL_SIZE=4096

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

  • 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: 

    CONFIG_MCUBOOT_ACTION_HOOKS=y

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

    if(CONFIG_MCUBOOT)
    
        zephyr_library()    
        zephyr_library_sources(mcuboot_hook.c)
    
    
    endif()

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

    #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);
    
    }

    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,

Reply
  • 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: 

    CONFIG_MCUBOOT_ACTION_HOOKS=y

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

    if(CONFIG_MCUBOOT)
    
        zephyr_library()    
        zephyr_library_sources(mcuboot_hook.c)
    
    
    endif()

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

    #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);
    
    }

    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,

Children
Related