OFF CHIP OTA UPDATE using external flash

I am working on this project off chip ota update on nRF5_SDK  using ecample/thread/dfu

by now, i have done changes in these functions on_data_obj_create_request() and on_data_obj_write_request(). initially these functions were erasing and writing data in internal flash which I changed to qspi functions like nrf_drv_qspi_erase() and nrf_drv_qspi_write(). and it works perfectly.

Later i changed functions for hash verification which is also working but i am not sure about what should be the next step so that bootloader changes the earlier application with the new firmware image.

Parents
  • Hi,

    Unfortunately our experts on this matter are out-of-office today. We expect to get back to you beginning of next week. If you have any progress in the mean time then please update this ticket with your findings.

    Regards,
    Terje

  • I have made three changes in code 

    1: in flash erase i have changed it to erase external flash using QSPI.

    static void on_data_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
    {
        NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (data)");
    
        if (!nrf_dfu_validation_init_cmd_present())
        {
            /* Can't accept data because DFU isn't initialized by init command. */
            NRF_LOG_ERROR("Cannot create data object without valid init command");
            p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
            return;
        }
    
        if (p_req->create.object_size == 0)
        {
            NRF_LOG_ERROR("Object size cannot be 0.")
            p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER;
            return;
        }
    
        if (  ((p_req->create.object_size & (CODE_PAGE_SIZE - 1)) != 0)
            && (s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size != m_firmware_size_req))
        {
            NRF_LOG_ERROR("Object size must be page aligned");
            ota_error_code = 1;
            p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER;
            return;
        }
    
        if (p_req->create.object_size > DATA_OBJECT_MAX_SIZE)
        {
            /* It is impossible to handle the command because the size is too large */
            NRF_LOG_ERROR("Invalid size for object (too large)");
            p_res->result = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES;
            return;
        }
    
        if ((s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size) >
            m_firmware_size_req)
        {
            NRF_LOG_ERROR("Creating the object with size 0x%08x would overflow firmware size. "
                          "Offset is 0x%08x and firmware size is 0x%08x.",
                          p_req->create.object_size,
                          s_dfu_settings.progress.firmware_image_offset_last,
                          m_firmware_size_req);
    
            p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
            ota_error_code = 2;
            return;
        }
    
        s_dfu_settings.progress.data_object_size      = p_req->create.object_size;
        s_dfu_settings.progress.firmware_image_crc    = s_dfu_settings.progress.firmware_image_crc_last;
        s_dfu_settings.progress.firmware_image_offset = s_dfu_settings.progress.firmware_image_offset_last;
        s_dfu_settings.write_offset                   = s_dfu_settings.progress.firmware_image_offset_last;
    
        /* Erase the page we're at. */
        if (nrf_dfu_flash_erase((m_firmware_start_addr + s_dfu_settings.progress.firmware_image_offset),
                                CEIL_DIV(p_req->create.object_size, CODE_PAGE_SIZE), NULL) != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Erase operation failed");
            p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT;
            return;
        }
    
        NRF_LOG_DEBUG("Creating object with size: %d. Offset: 0x%08x, CRC: 0x%08x",
                     s_dfu_settings.progress.data_object_size,
                     s_dfu_settings.progress.firmware_image_offset,
                     s_dfu_settings.progress.firmware_image_crc);
        
       NRF_LOG_INFO("Creating object with size: %d.  Offset: 0x%08x, CRC: 0x%08x\r\n",
                     s_dfu_settings.progress.data_object_size,
                     s_dfu_settings.progress.firmware_image_offset,
                     s_dfu_settings.progress.firmware_image_crc);
    
    
          /* check if flash is enabled */
            if(is_flash_enable() == false)
            {
              NRF_LOG_INFO("Flash in sleep state. Reinintialising\r\n");
    
              Enable_Flash();
            }
    
            if(nrf_drv_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, FIRMWARE_FLASH_ADDR + (s_dfu_settings.progress.firmware_image_offset)) != NRFX_SUCCESS)
            {
              NRF_LOG_INFO("Failed to rrase data blocks in Ext Flash.\r\n");
            }
            else
            {
              NRF_LOG_INFO("Succsessfully Erased Ext Flash block at: 0x%X\r\n\r\n",FIRMWARE_FLASH_ADDR + (s_dfu_settings.progress.firmware_image_offset));
              WAIT_FOR_PERIPH();
              nrf_delay_ms(500);
            }
    
    
    }
     

    2: in flash store I have changed to write the code in external flash using QSPI.

    static void on_data_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
    {
        NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (data)");
    
        if (!nrf_dfu_validation_init_cmd_present())
        {
            /* Can't accept data because DFU isn't initialized by init command. */
            p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
            return;
        }
    
        uint32_t const data_object_offset = s_dfu_settings.progress.firmware_image_offset -
                                            s_dfu_settings.progress.firmware_image_offset_last;
    
        if ((p_req->write.len + data_object_offset) > s_dfu_settings.progress.data_object_size)
        {
            /* Can't accept data because too much data has been received. */
            NRF_LOG_ERROR("Write request too long");
            p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER;
            return;
        }
    
    
    
        uint32_t const write_addr = m_firmware_start_addr + s_dfu_settings.write_offset;
        /* CRC must be calculated before handing off the data to fstorage because the data is
         * freed on write completion.
         */
        uint32_t const next_crc =
            crc32_compute(p_req->write.p_data, p_req->write.len, &s_dfu_settings.progress.firmware_image_crc);
    
        ASSERT(p_req->callback.write);
    
        ret_code_t ret = NRF_ERROR_BASE_NUM;
          //ret_code_t ret =
          //  nrf_dfu_flash_store(write_addr, p_req->write.p_data, p_req->write.len, p_req->callback.write);
    
            
            /* check if flash is enabled */
            if(is_flash_enable() == false)
            {
              NRF_LOG_INFO("Flash in sleep state. Reinintialising\r\n");
    
              Enable_Flash();
            }
            
            
            if(nrf_drv_qspi_write(p_req->write.p_data, p_req->write.len,FIRMWARE_FLASH_ADDR + s_dfu_settings.write_offset) != NRFX_SUCCESS)
            {
              NRF_LOG_INFO("\r\nFailed storing data blocks in Ext Flash.\r\n");
            }
            else
            {
              NRF_LOG_INFO("Succsessfully storing data block at: 0x%X\r\n\r\n",FIRMWARE_FLASH_ADDR + s_dfu_settings.write_offset);
              WAIT_FOR_PERIPH();
              p_req->callback.write((void*)p_req->write.p_data);
              ret = NRF_SUCCESS;
            }
    
        if (ret != NRF_SUCCESS)
        {
            /* When nrf_dfu_flash_store() fails because there is no space in the queue,
             * stop processing the request so that the peer can detect a CRC error
             * and retransmit this object. Remember to manually free the buffer !
             */
            p_req->callback.write((void*)p_req->write.p_data);
            return;
        }
    
        /* Update the CRC of the firmware image. */
        s_dfu_settings.write_offset                   += p_req->write.len;
        s_dfu_settings.progress.firmware_image_offset += p_req->write.len;
        s_dfu_settings.progress.firmware_image_crc     = next_crc;
    
        /* This is only used when the PRN is triggered and the 'write' message
         * is answered with a CRC message and these field are copied into the response.
         */
        p_res->write.crc    = s_dfu_settings.progress.firmware_image_crc;
        p_res->write.offset = s_dfu_settings.progress.firmware_image_offset;
    }

    3: in calculate hash i have changed it to copy data from QSPI and update the hash accordingly.

    ret_code_t nrf_crypto_hash_calculate(nrf_crypto_hash_context_t    * const p_context,
                                         nrf_crypto_hash_info_t       const * p_info,
                                         uint8_t                      const * p_data,
                                         size_t                               data_size,
                                         uint8_t                            * p_digest,
                                         size_t                       * const p_digest_size)
    {
        ret_code_t                      ret_val;
        nrf_crypto_hash_context_t     * p_ctx  = (nrf_crypto_hash_context_t *)p_context;
        void                          * p_allocated_context = NULL;
    
    // Internal allocation of context not available for CC310_BL in order to save code size.
    #if defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED == 1)
        
        // Do nothing
        
    #elif defined(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED) && (NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED == 0)
        
        // Validate input. Only validate input parameters that are used locally, others are validated
        // in the init, update and/or finalize functions.
        VERIFY_TRUE(p_info != NULL, NRF_ERROR_CRYPTO_INPUT_NULL);
    
        // Allocate context if needed (not provided by the user).
        if (p_context == NULL)
        {
            p_allocated_context = NRF_CRYPTO_ALLOC(p_info->context_size);
            if (p_allocated_context == NULL)
            {
                return NRF_ERROR_CRYPTO_ALLOC_FAILED;
            }
            p_ctx = (nrf_crypto_hash_context_t *)p_allocated_context;
        }
        
    #else
    
        #warning NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED define not found in sdk_config.h (Is the sdk_config.h valid?).
        
    #endif // NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED
    
        ret_val = nrf_crypto_hash_init(p_ctx, p_info);
        NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context);
    
    
        if(validation_state == 0)
        {
            ret_val = nrf_crypto_hash_update(p_ctx, p_data, data_size);
            NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context);
            validation_state = 1;
        }
        else
        {
            uint16_t firmware_blocks = data_size / FIRMWARE_BLOCK_SIZE;
            uint8_t rest_block = data_size % FIRMWARE_BLOCK_SIZE;
    
    
            printf("data_size: %d", data_size);
            printf("firmware_blocks: %d", firmware_blocks);
            printf("rest_block: %d", rest_block);
    
    
            for(uint16_t i=0; i <= firmware_blocks; i++)
            {
              /* check if flash is enabled */
                if(is_flash_enable() == false)
                {
                    printf("Flash in sleep state. Reinintialising\r\n");
    
                    Enable_Flash();
                }
            
                uint8_t m_buffer_rx[FIRMWARE_BLOCK_SIZE];
    
                if(i == firmware_blocks)
                {
                    if(nrf_drv_qspi_read(m_buffer_rx, rest_block,FIRMWARE_FLASH_ADDR + (FIRMWARE_BLOCK_SIZE * i)) != NRFX_SUCCESS)
                    {
                       printf("\r\nFailed read data blocks in Ext Flash.\r\n");
                    }
                    else
                    {
                       printf("Succsessfully read rest_block data block from: 0x%X\r\n\r\n",FIRMWARE_FLASH_ADDR + (FIRMWARE_BLOCK_SIZE * i));
                       WAIT_FOR_PERIPH();
                       ret_val = nrf_crypto_hash_update(p_ctx, m_buffer_rx, rest_block);
                       NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context);
                    }
                }
                else
                {
                    if(nrf_drv_qspi_read(m_buffer_rx, FIRMWARE_BLOCK_SIZE,FIRMWARE_FLASH_ADDR + (FIRMWARE_BLOCK_SIZE * i)) != NRFX_SUCCESS)
                    {
                        printf("\r\nFailed read data blocks in Ext Flash.\r\n");
                    }
                    else
                    {
                        printf("Succsessfully read data block %d from: 0x%X\r\n\r\n", i ,FIRMWARE_FLASH_ADDR + (FIRMWARE_BLOCK_SIZE * i));
                        WAIT_FOR_PERIPH();
                        ret_val = nrf_crypto_hash_update(p_ctx, m_buffer_rx, FIRMWARE_BLOCK_SIZE);
                        NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context);
                    }
                }            
            }
            validation_state = 0;
        }
    
        ret_val = nrf_crypto_hash_finalize(p_ctx, p_digest, p_digest_size);
        NRF_CRYPTO_VERIFY_SUCCESS_DEALLOCATE(ret_val, p_allocated_context);
    
    #if !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256)
        // Free context if allocated internally
        if (p_allocated_context != NULL)
        {
            NRF_CRYPTO_FREE(p_allocated_context);
        }
    #endif // !NRF_MODULE_ENABLED(NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256)
    
        return NRF_SUCCESS;
    }
    
    #endif // NRF_MODULE_ENABLED(NRF_CRYPTO_HASH)
    
    #endif // NRF_MODULE_ENABLED(NRF_CRYPTO)

    and after that few more changes to get notified that hash has been verified and also to find out flow of the code 

    1

    #if NRF_DFU_IN_APP
            res.result = nrf_dfu_validation_post_data_execute(m_firmware_start_addr, m_firmware_size_req);
            printf("Post Validation Error Code: %d\r\n",res.result );
    
            #else
            res.result = nrf_dfu_validation_activation_prepare(m_firmware_start_addr, m_firmware_size_req);
            #endif

    2 and in this this change i didn't find the output after this  if (!is_trusted). may be this piece of code is not executing or something

    nrf_dfu_result_t postvalidate(uint32_t data_addr, uint32_t data_len, bool is_trusted)
    {
        nrf_dfu_result_t           ret_val = NRF_DFU_RES_CODE_SUCCESS;
        dfu_init_command_t const * p_init  = mp_init;
    
        if (!fw_hash_ok(p_init, data_addr, data_len))
        {
            ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_VERIFICATION_FAILED);
        }
        else
        {
            printf("postvalidate Hash ok\r\n");
          
            if (p_init->type == DFU_FW_TYPE_APPLICATION)
            {
                if (!postvalidate_app(p_init, data_addr, data_len, is_trusted))
                {
                    ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT;
                    printf("postvalidate fun error: postvalidate_app %d\r\n",ret_val);
                }
                else
                {
                  printf("postvalidate fun success\r\n");
                }
            }
    #if NRF_DFU_SUPPORTS_EXTERNAL_APP
            else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
            {
                if (!is_trusted)
                {
                    // This function must be implemented externally
                    ret_val = nrf_dfu_validation_post_external_app_execute(p_init, is_trusted);
                }
                else
                {
                    s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_EXT_APP;
                }
            }
    #endif // NRF_DFU_SUPPORTS_EXTERNAL_APP
            else
            {
                bool with_sd = p_init->type & DFU_FW_TYPE_SOFTDEVICE;
                bool with_bl = p_init->type & DFU_FW_TYPE_BOOTLOADER;
    
                if (!postvalidate_sd_bl(p_init, with_sd, with_bl, data_addr, data_len, is_trusted))
                {
                    ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT;
                    if (is_trusted && with_sd && !DFU_REQUIRES_SOFTDEVICE &&
                        (data_addr == nrf_dfu_softdevice_start_address()))
                    {
                        nrf_dfu_softdevice_invalidate();
                    }
                }
            }
        }
    
        if (!is_trusted)
        {
            if (ret_val == NRF_DFU_RES_CODE_SUCCESS)
            {
                    printf("\r\nSet DFU setting current bank.\r\n");
    
                s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1;
            }
            else
            {
                printf("nrf_dfu_settings_progress_reset if !is_trusted\r\n");
    
                nrf_dfu_settings_progress_reset();
            }
        }
        else
        {
            if (ret_val == NRF_DFU_RES_CODE_SUCCESS)
            {
            printf("Mark the update as complete and valid.\r\n");
                // Mark the update as complete and valid.
                s_dfu_settings.bank_1.image_crc  = crc32_compute((uint8_t *)data_addr, data_len, NULL);
                s_dfu_settings.bank_1.image_size = data_len;
            }
            else
            {
                nrf_dfu_bank_invalidate(&s_dfu_settings.bank_1);
                        printf("Mark the update as Invalid. : %d\r\n",ret_val);
    
            }
    
            printf("nrf_dfu_settings_progress_reset if is_trusted\r\n");
    
            nrf_dfu_settings_progress_reset();
            s_dfu_settings.progress.update_start_address = data_addr;
        }
    
        return ret_val;
    }
    

    3

    static bool nrf_dfu_validation_hash_ok(uint8_t const * p_hash, uint32_t src_addr, uint32_t data_len, bool little_endian)
    {
        ret_code_t err_code;
        bool       result   = true;
        uint8_t    hash_be[NRF_CRYPTO_HASH_SIZE_SHA256];
        size_t     hash_len = NRF_CRYPTO_HASH_SIZE_SHA256;
    
        nrf_crypto_hash_context_t hash_context = {0};
    
        crypto_init();
    
        if (little_endian)
        {
            // Convert to hash to big-endian format for use in nrf_crypto.
            nrf_crypto_internal_swap_endian(hash_be,
                                            p_hash,
                                            NRF_CRYPTO_HASH_SIZE_SHA256);
            p_hash = hash_be;
        }
    
        NRF_LOG_DEBUG("Hash verification. start address: 0x%x, size: 0x%x",
                      src_addr,
                      data_len);
    
       NRF_LOG_INFO("Hash verification. start address: 0x%x, size: 0x%x",
                      src_addr,
                      data_len);
    
    
        err_code = nrf_crypto_hash_calculate(&hash_context,
                                             &g_nrf_crypto_hash_sha256_info,
                                             (uint8_t*)src_addr,
                                             data_len,
                                             m_fw_hash,
                                             &hash_len);
    
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Could not run hash verification (err_code 0x%x).", err_code);
            result = false;
        }
        else if (memcmp(m_fw_hash, p_hash, NRF_CRYPTO_HASH_SIZE_SHA256) != 0)
        {
            NRF_LOG_WARNING("Hash verification failed.");
            NRF_LOG_INFO("Hash verification failed.");
            NRF_LOG_DEBUG("Expected FW hash:")
            NRF_LOG_INFO("Expected FW hash:")
            NRF_LOG_HEXDUMP_DEBUG(p_hash, NRF_CRYPTO_HASH_SIZE_SHA256);
            NRF_LOG_DEBUG("Actual FW hash:")
            NRF_LOG_INFO("Actual FW hash:")
            NRF_LOG_HEXDUMP_DEBUG(m_fw_hash, NRF_CRYPTO_HASH_SIZE_SHA256);
            NRF_LOG_FLUSH();
    
            result = false;
        }
    
        return result;
    }

  • Are you copying the image from bank 1 in external flash? I can't tell from your code snippet where the image is copied from.

  • Bank 1 is the temporary address where the app was initially supposed to be downloaded, but I changed it to external flash.

    Bank 0 is the address in the internal flash where the app runs after the download completes. In the bootloader, we erase the old image from bank 0 and replace it with bank 1 (in this case, external flash) after performing a CRC check.

  • Yes, but you are not showing how you adapted the copy function to read the image from external flash.

  • i have changed the image_copy function and in logs i can see it is working and writes my image completely

    after this i have shared a code snippet of image_copy() inside that i have changed this

    // Flash one page

    uint32_t m_buffer_rx[bytes];

    if(nrf_drv_qspi_read(m_buffer_rx, bytes,firmware_flash_addr ) != NRFX_SUCCESS)
    {
    NRF_LOG_INFO("Failed read application for bootloader reset in Ext Flash.\r\n");
    }
    else
    {
    NRF_LOG_INFO("Succsessfully read application for bootloader reset from: 0x%lX\r\n",firmware_flash_addr);
    WAIT_FOR_PERIPH();
    NRF_LOG_DEBUG("Copying 0x%x to 0x%x, size: 0x%x", src_addr, dst_addr, bytes);
    ret_val = nrf_dfu_flash_store(dst_addr,
    (uint32_t *)m_buffer_rx,
    ALIGN_NUM(sizeof(uint32_t), bytes),
    NULL);
    }

    and code which was earlier copying the image is here:


    //NRF_LOG_DEBUG("Copying 0x%x to 0x%x, size: 0x%x", src_addr, dst_addr, bytes);
    //ret_val = nrf_dfu_flash_store(dst_addr,
    // (uint32_t *)src_addr,
    // ALIGN_NUM(sizeof(uint32_t), bytes),
    // NULL);

  • It looks like you are using the QSPI flash API correctly. Could you please read out the image stored in the QSPI flash and compare it to the image stored in Bank 1 to see if they match?

Reply Children
  • To read from the external flash, a specific command is required by the nrfprog tool. Unfortunately, while retrieving data from the external flash, this command appends the address to each line, thereby impeding the direct comparison between the data retrieved from the internal and external flash sources.

    Furthermore, regarding the progress of the DFU process, I'd like to inform you that we have reached the final stages:

    1. The application has been successfully downloaded to the external flash.
    2. Hash verification has been completed without any issues.
    3. DFU bank 1 has been appropriately configured.
    4. The bootloader has been reset as per the protocol.
    5. The bootloader is effectively replacing the entire code from the external flash to the internal flash.
    6. Upon replacement, a CRC computation over the image in the internal flash is conducted. However, this step encounters failure, and despite diligent efforts, the root cause behind this failure remains elusive.
  • You can use regex or a text processing tool like 'awk' to filter out the address column from the output.

    Example of using regex in Vs code:

  • hey I tried all possible commands to read external qspi flash, but as I am using custom board none of them worked. 

    so i tried another way. even though crc calculation fails, i jumped to start the app directly buy changing the code in nrf_bootloader_init() function and my dfu is complete after this.

    return NRF_ERROR_INTERNAL; // Should not reach this.

    case ACTIVATION_ERROR:
    default:
    return NRF_ERROR_INTERNAL;
    }

    if (dfu_enter)
    {
    nrf_bootloader_app_start();
    nrf_bootloader_wdt_init();
    scheduler_init();
    dfu_enter_flags_clear();

    // Call user-defined init function if implemented
    ret_val = nrf_dfu_init_user();
    if (ret_val != NRF_SUCCESS)
    {
    return NRF_ERROR_INTERNAL;
    }

    nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout);

    in above juggad code nrf_bootloader_app_start(); function is used to start the app code. and it works and my app version 2 is working perfectlly.

    my device sends Payloads on server and on the server i can see the update and ota version as well.

    in this payload you can see at the last 2 is wrrten which represents the app version.

    and in another payload ota done message is visible.

    and also in j link it is visible 

    even this ota is done but still why that crc calculation fails? and if let this run then without crc verification this ota process is just like the single bank dfu process. 

    so please help me in this crc calculation

  • I would still like you to verify that the updated binary stored in the bank 0 matches the binary you uploaded through DFU. Since you are not able to read data from your external flash, you can program the hex file of your new application to the device, then read out the memory. Then, repeat the same steps but when loading the image through DFU and not via the debug interface.

    If the images are identical, then that suggests that the CRC computed by the application and the one computed by the bootloader were not computed over the same area.

  • I simply flashed the same application twice using j link(not dfu) by following all the steps .

    and still there is difference in both hex files.


    dnk124 ~ nrfjprog --memrd 0x0 --n 1048576 > flash_on_board.hex
    dnk124 ~ nrfjprog --memrd 0x0 --n 1048576 > flash_on_board2.hex
    dnk124 ~ cmp flash_on_board.hex flash_on_board2.hex
    flash_on_board.hex flash_on_board2.hex differ: byte 1762439, line 25543
    dnk124 ~ 1 diff flash_on_board.hex flash_on_board2.hex
    25543,25544c25543,25544
    < 0x00063C60: 20206365 30322037 31203332 39313A38 |ec 7 2023 18:19|
    < 0x00063C70: 0038323A 6F727245 6E692072 61687320 |:28.Error in sha|
    ---
    > 0x00063C60: 20206365 30322037 31203332 33323A38 |ec 7 2023 18:23|
    > 0x00063C70: 0035353A 6F727245 6E692072 61687320 |:55.Error in sha|
    60938,60943c60938,60943
    < 0x000EE090: FFFF0026 C4320402 00000000 000003EA |&.....2.........|
    < 0x000EE0A0: 000003EB 0504C84E 147D016A 2D24DB7D |....N...j.}.}.$-|
    < 0x000EE0B0: 7A2DC0CC DC4F0076 0AB10002 FFF40007 |..-zv.O.........|
    < 0x000EE0C0: FFFF0020 3D33E0D3 C5638CC0 E76FBB73 | .....3=..c.s.o.|
    < 0x000EE0D0: 8D48228A 5967488E D7E90C97 8F3891A9 |."H..HgY......8.|
    < 0x000EE0E0: 3F784A25 FFFFFFFF FFFFFFFF FFFFFFFF |%Jx?............|
    ---
    > 0x000EE090: FFFF0026 C4330402 00000000 000003EA |&.....3.........|
    > 0x000EE0A0: 000003EB 0504C84E E9DEB6BA AEDF0E4C |....N.......L...|
    > 0x000EE0B0: 8B4A8FCE 8EEED222 0AB10002 FFF40007 |..J."...........|
    > 0x000EE0C0: FFFF0020 787E306D 482D2AD0 06EE9446 | ...m0~x.*-HF...|
    > 0x000EE0D0: 062B3A5A 0069BE23 1EA55933 1806B761 |Z:+.#.i.3Y..a...|
    > 0x000EE0E0: 56F8A127 FFFFFFFF FFFFFFFF FFFFFFFF |'..V............|
    65025,65026c65025,65026
    < 0x000FE000: 1341AA60 00000002 00000001 00000001 |`.A.............|
    < 0x000FE010: 00000000 00000000 00064F38 895C458F |........8O...E\.|
    ---
    > 0x000FE000: AD7C8D5D 00000002 00000001 00000001 |].|.............|
    > 0x000FE010: 00000000 00000000 00064F38 C9CBBF5C |........8O..\...|
    65062c65062
    < 0x000FE250: 00000000 00000000 00000000 37CD1E9A |...............7|
    ---
    > 0x000FE250: 00000000 00000000 00000000 151DE479 |............y...|
    65067c65067
    < 0x000FE2A0: 458F0100 0000895C 00000000 00000000 |...E\...........|
    ---
    > 0x000FE2A0: BF5C0100 0000C9CB 00000000 00000000 |..\.............|
    65281,65282c65281,65282
    < 0x000FF000: 1341AA60 00000002 00000001 00000001 |`.A.............|
    < 0x000FF010: 00000000 00000000 00064F38 895C458F |........8O...E\.|
    ---
    > 0x000FF000: AD7C8D5D 00000002 00000001 00000001 |].|.............|
    > 0x000FF010: 00000000 00000000 00064F38 C9CBBF5C |........8O..\...|
    65318c65318
    < 0x000FF250: 00000000 00000000 00000000 37CD1E9A |...............7|
    ---
    > 0x000FF250: 00000000 00000000 00000000 151DE479 |............y...|
    65323c65323
    < 0x000FF2A0: 458F0100 0000895C 00000000 00000000 |...E\...........|
    ---
    > 0x000FF2A0: BF5C0100 0000C9CB 00000000 00000000 |..\.............|
    dnk124 ~ 1

Related